Source Code Cross Referenced for ComponentTester.java in  » Testing » abbot-1.0.1 » abbot » tester » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » abbot 1.0.1 » abbot.tester 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package abbot.tester;
0002:
0003:        import java.awt.AWTEvent;
0004:        import java.awt.Component;
0005:        import java.awt.Frame;
0006:        import java.awt.Point;
0007:        import java.awt.event.*;
0008:        import java.lang.reflect.Method;
0009:        import java.util.ArrayList;
0010:        import java.util.Arrays;
0011:        import java.util.HashMap;
0012:        import java.util.HashSet;
0013:        import java.util.Set;
0014:
0015:        import javax.accessibility.AccessibleContext;
0016:        import javax.accessibility.AccessibleIcon;
0017:
0018:        import abbot.BugReport;
0019:        import abbot.Log;
0020:        import abbot.WaitTimedOutError;
0021:        import abbot.finder.AWTHierarchy;
0022:        import abbot.finder.BasicFinder;
0023:        import abbot.finder.ComponentFinder;
0024:        import abbot.finder.ComponentNotFoundException;
0025:        import abbot.finder.ComponentSearchException;
0026:        import abbot.finder.Hierarchy;
0027:        import abbot.finder.MultipleComponentsFoundException;
0028:        import abbot.finder.matchers.WindowMatcher;
0029:        import abbot.i18n.Strings;
0030:        import abbot.script.ComponentReference;
0031:        import abbot.util.*;
0032:
0033:        /** Provides basic programmatic operation of a {@link Component} and related
0034:         UI objects such as windows, menus and menu bars throuh action methods.
0035:         Also provides some useful assertions about properties of a {@link
0036:         Component}.  
0037:         <p>
0038:         There are two sets of event-generating methods.  The internal, protected
0039:         methods inherited from {@link abbot.tester.Robot abbot.tester.Robot} are
0040:         for normal programmatic use within derived Tester classes.  No event queue
0041:         synchronization should be performed except when modifying a component for
0042:         which results are required for the action itself.
0043:         <p>
0044:         The public <code>actionXXX</code> functions are meant to be invoked from a
0045:         script or directly from a hand-written test.  These actions are
0046:         distinguished by name, number of arguments, and by argument type.  The
0047:         actionX methods will be synchronized with the event dispatch thread when
0048:         invoked, so you should only do synchronization with waitForIdle when you
0049:         depend on the results of a particular event prior to sending the next one
0050:         (e.g. scrolling a table cell into view before selecting it).
0051:         All public action methods should ensure that the actions they
0052:         trigger are finished on return, or will be finished before any subsequent
0053:         actions are requested.
0054:         <p>
0055:         <i>Action</i> methods generally represent user-driven actions such
0056:         as menu selection, table selection, popup menus, etc.  All actions should
0057:         have the following signature:
0058:         <blockquote>
0059:         <code>public void actionSpinMeRoundLikeARecord(Component c, ...);</code>
0060:         <code>public void actionPinchMe(Component c, ComponentLocation loc);</code>
0061:         </blockquote>
0062:         <p>
0063:         It is essential that the argument is of type {@link Component}; if you use
0064:         a more-derived class, then the actual invocation becomes ambiguous since
0065:         method parsing doesn't attempt to determine which identically-named method
0066:         is the most-derived.
0067:         <p>
0068:         The {@link ComponentLocation} abstraction allows all derived tester
0069:         classes to inherit click, popup menu, and drag variants without having to
0070:         explicitly define new methods for component-specific substructures.  The
0071:         new class need only define the {@link #parseLocation(String)} method,
0072:         which should return a location specific to the component in question.
0073:         <p> 
0074:         <i>Assertions</i> are either independent of any component (and should be
0075:         implemented in this class), or take a component as the first argument, and
0076:         perform some check on that component.  All assertions should have one of
0077:         the following signatures:
0078:         <blockquote> 
0079:         <code>public boolean assertMyself(...);</code><br>
0080:         <code>public boolean assertBorderIsAtrociouslyUgly(Component c, ...);</code>
0081:         </blockquote>
0082:         Note that these assertions do not throw exceptions but rather return a
0083:         <code>boolean</code> value indicating success or failure.  Normally these
0084:         assertions will be wrapped by an abbot.script.Assert step if you want to
0085:         cause a test failure, or you can manually throw the proper failure
0086:         exception if the method returns false.
0087:         <p>
0088:         <i>Property checks</i> may also be implemented in cases where the component
0089:         "property" might not be readily available or easily comparable, e.g.
0090:         see {@link abbot.tester.JPopupMenuTester#getMenuLabels(Component)}.
0091:         <blockquote>
0092:         <code>public Object getHairpiece(Component c);</code><br>
0093:         <code>public boolean isRighteouslyIndignant(Component c);</code>
0094:         </blockquote>
0095:         Any non-property methods with the property signature, should be added to
0096:         the {@link #IGNORED_METHODS} set, since property-like methods are scanned
0097:         dynamically to populate the {@link abbot.editor.ScriptEditor editor}'s
0098:         action menus. 
0099:         <p>
0100:         <a name=Customization>
0101:         <h2>Extending ComponentTester</h2>
0102:         Following are the steps required to implement a Tester object for a custom
0103:         class.
0104:         <ul>
0105:         <li><h3>Create the Tester Class</h3>
0106:         Derive from this class to implement actions and assertions specific to
0107:         a given component class.  Testers for any classes found in the JRE
0108:         (i.e. in the {@link java.awt} or {@link javax.swing} packages) should be
0109:         in the {@link abbot.tester abbot.tester} package.  Extensions (testers for
0110:         any <code>Component</code> subclasses not found in the JRE) must be in the
0111:         <code>abbot.tester.extensions</code> package and be
0112:         named the name of the <code>Component</code> subclass followed by "Tester".
0113:         For example, the {@link javax.swing.JButton javax.swing.JButton} tester
0114:         class is {@link JButtonTester abbot.tester.JButtonTester}, and a tester
0115:         for <code>org.me.PR0NViewer</code> would be
0116:         <code>abbot.tester.extensions.PR0NViewerTester</code>.  
0117:         <li><h3>Add Action Methods</h3>
0118:         Add <code>action</code> methods which effect user actions.
0119:         See the section on <a href=Naming>naming conventions</a> below.
0120:         <li><h3>Add Assertion Methods</h3>
0121:         Add <code>assert</code> methods to access attributes not readily available
0122:         as properties<br> 
0123:         <li><h3>Add Substructure Support</h3>
0124:         Add a corresponding <code>ComponentLocation</code> implementation to
0125:         handle any substructure present in your <code>Component</code>.
0126:         See {@link ComponentLocation} for details.
0127:         <li><h3>Add Substructure-handling Methods</h3>
0128:         <ul>
0129:         <li>{@link #parseLocation(String)}<br>
0130:         Convert the given <code>String</code> into an instance of
0131:         {@link ComponentLocation} specific to your Tester.  Here is an example
0132:         implementation from {@link JListTester}:<br>
0133:         <code><pre>
0134:         public ComponentLocation parseLocation(String encoded) {
0135:         return new JListLocation().parse(encoded);
0136:         }
0137:         </pre></code>
0138:         <li>{@link #getLocation(Component,Point)}<br>
0139:         Use the given <code>Point</code> to create a {@link ComponentLocation}
0140:         instance appropriate for the <code>Component</code> substructure
0141:         available at that location.  For example, on a {@link javax.swing.JList},
0142:         you would return a {@link JListLocation} based on the
0143:         stringified value at that location, the row/index at that
0144:         location, or the raw <code>Point</code>,
0145:         in order of preference.  If a stringified value is unavailable,
0146:         fall back to an indexed position; if that is not possible (if, for
0147:         instance, the location is outside the list contents), return a
0148:         {@link ComponentLocation} based on the raw <code>Point</code>.
0149:         </ul>
0150:         <li><h3>Set Editor Properties</h3>
0151:         Add-on tester classes should set the following system properties so that
0152:         the actions provided by their tester can be properly displayed in the
0153:         script editor.  For an action <code>actionWiggle</code> provided by class
0154:         <code>abbot.tester.extensions.PR0NViewerTester</code>, the following
0155:         properties should be defined:<br>
0156:         <ul>
0157:         <li><code>actionWiggle.menu</code> short name for Insert menu
0158:         <li><code>actionWiggle.desc</code> short description (optional)
0159:         <li><code>actionWiggle.icon</code> icon for the action (optional)
0160:         <li><code>PR0NViewerTester.actionWiggle.args</code> javadoc-style
0161:         description of method, displayed when asking the user for its arguments
0162:         </ul>
0163:         Since these properties are global, if your Tester class defines a method
0164:         which is also defined by another Tester class, you must supply the class
0165:         name as a prefix to the property.   
0166:         </ul>
0167:         <p>
0168:         <a name=MethodNaming>
0169:         <h2>Method Naming Conventions</h2>
0170:         Action methods should be named according to the human-centric action that
0171:         is being performed if at all possible.  For example, use
0172:         <code>actionSelectRow</code> in a List rather than
0173:         <code>actionSelectIndex</code>.  If there's no common usage, or if the
0174:         usage is too vague or diverse, use the specific terms used in code. 
0175:         For example, {@link JScrollBarTester} uses
0176:         {@link JScrollBarTester#actionScrollUnitUp(Component) actionScrollUnitUp()}
0177:         and 
0178:         {@link JScrollBarTester#actionScrollBlockUp(Component) actionScrollBlockUp()};
0179:         since there is no common language usage for these
0180:         concepts (line and page exist, but are not appropriate if what is scrolled
0181:         is not text). 
0182:         <p>
0183:         When naming a selection method, include the logical substructure target of
0184:         the selection in the name (e.g.
0185:         {@link JTableTester#actionSelectCell(Component,JTableLocation)}
0186:         JTableTester.actionSelectCell()),
0187:         since some components may have more than one type of selectable item
0188:         within them.  
0189:         */
0190:        public class ComponentTester extends Robot {
0191:
0192:            /** Add any method names here which should <em>not</em> show up in a
0193:                dynamically generated list of property methods.
0194:             */
0195:            protected static Set IGNORED_METHODS = new HashSet();
0196:
0197:            static {
0198:                // Omit from method lookup deprecated methods or others we want to
0199:                // ignore 
0200:                IGNORED_METHODS.addAll(Arrays.asList(new String[] {
0201:                        "actionSelectAWTMenuItemByLabel",
0202:                        "actionSelectAWTPopupMenuItemByLabel", "getTag",
0203:                        "getTester", "isOnPopup", "getLocation", }));
0204:            }
0205:
0206:            /** Maps class names to their corresponding Tester object. */
0207:            private static HashMap testers = new HashMap();
0208:
0209:            /** Establish the given ComponentTester as the one to use for the given
0210:             * class.  This may be used to override the default tester for a given
0211:             * core class.  Note that this will only work with components loaded by
0212:             * the framework class loader, not those loaded by the class loader for
0213:             * the code under test.
0214:             */
0215:            public static void setTester(Class forClass, ComponentTester tester) {
0216:                testers.put(forClass.getName(), tester);
0217:            }
0218:
0219:            /** Return a shared instance of the appropriate
0220:                <code>ComponentTester</code> for the given {@link Component}.<p>
0221:                This method is primarily used by the scripting system, since the
0222:                appropriate <code>ComponentTester</code> for a given {@link Component}
0223:                is not known <i>a priori</i>.  Coded unit tests should generally just
0224:                create an instance of the desired type of <code>ComponentTester</code>
0225:                for local use. 
0226:             */
0227:            public static ComponentTester getTester(Component comp) {
0228:                return comp != null ? getTester(comp.getClass())
0229:                        : getTester(Component.class);
0230:            }
0231:
0232:            /** Return a shared instance of the corresponding
0233:                <code>ComponentTester</code> object for the given {@link Component}
0234:                class, chaining up the inheritance tree if no specific tester is found
0235:                for that class.<p> 
0236:                The abbot tester package is searched first, followed by the tester
0237:                extensions package.<p>
0238:                This method is primarily used by the scripting system, since the
0239:                appropriate <code>ComponentTester</code> for a given Component is not
0240:                known <i>a priori</i>.  Coded unit tests should generally just create
0241:                an instance of the desired type of <code>ComponentTester</code> for
0242:                local use. 
0243:             */
0244:            public static ComponentTester getTester(Class componentClass) {
0245:                String className = componentClass.getName();
0246:                ComponentTester tester = (ComponentTester) testers
0247:                        .get(className);
0248:                if (tester == null) {
0249:                    if (!Component.class.isAssignableFrom(componentClass)) {
0250:                        String msg = "Class " + className
0251:                                + " is not derived from java.awt.Component";
0252:                        throw new IllegalArgumentException(msg);
0253:                    }
0254:                    Log.debug("Looking up tester for " + componentClass);
0255:                    String testerName = simpleClassName(componentClass)
0256:                            + "Tester";
0257:                    Package pkg = ComponentTester.class.getPackage();
0258:                    String pkgName = "";
0259:                    if (pkg == null) {
0260:                        Log.warn("ComponentTester.class has null package; "
0261:                                + "the class loader is likely flawed: "
0262:                                + ComponentTester.class.getClassLoader()
0263:                                + ", "
0264:                                + Thread.currentThread()
0265:                                        .getContextClassLoader(),
0266:                                Log.FULL_STACK);
0267:                        pkgName = "abbot.tester";
0268:                    } else {
0269:                        pkgName = pkg.getName();
0270:                    }
0271:                    if (className.startsWith("javax.swing.")
0272:                            || className.startsWith("java.awt.")) {
0273:                        tester = findTester(pkgName + "." + testerName,
0274:                                componentClass);
0275:                    }
0276:                    if (tester == null) {
0277:                        tester = findTester(pkgName + ".extensions."
0278:                                + testerName, componentClass);
0279:                        if (tester == null) {
0280:                            tester = getTester(componentClass.getSuperclass());
0281:                        }
0282:                    }
0283:                    if (tester != null && !tester.isExtension()) {
0284:                        // Only cache it if it's part of the standard framework,
0285:                        // but cache it for every level that we looked up, so we
0286:                        // don't repeat the effort.
0287:                        testers.put(componentClass.getName(), tester);
0288:                    }
0289:                }
0290:
0291:                return tester;
0292:            }
0293:
0294:            /** Return whether this tester is an extension. */
0295:            public final boolean isExtension() {
0296:                return getClass().getName().startsWith(
0297:                        "abbot.tester.extensions");
0298:            }
0299:
0300:            /** Look up the given class, using special class loading rules to maintain
0301:                framework consistency. */
0302:            private static Class resolveClass(String testerName,
0303:                    Class componentClass) throws ClassNotFoundException {
0304:                // Extension testers must be loaded in the context of the code under
0305:                // test.
0306:                Class cls;
0307:                if (testerName.startsWith("abbot.tester.extensions")) {
0308:                    cls = Class.forName(testerName, true, componentClass
0309:                            .getClassLoader());
0310:                } else {
0311:                    cls = Class.forName(testerName);
0312:                }
0313:                Log.debug("Loaded class " + testerName + " with "
0314:                        + cls.getClassLoader());
0315:                return cls;
0316:            }
0317:
0318:            /** Look up the given class with a specific class loader. */
0319:            private static ComponentTester findTester(String testerName,
0320:                    Class componentClass) {
0321:                ComponentTester tester = null;
0322:                Class testerClass = null;
0323:                try {
0324:                    testerClass = resolveClass(testerName, componentClass);
0325:                    tester = (ComponentTester) testerClass.newInstance();
0326:                } catch (InstantiationException ie) {
0327:                    Log.warn(ie);
0328:                } catch (IllegalAccessException iae) {
0329:                    Log.warn(iae);
0330:                } catch (ClassNotFoundException cnf) {
0331:                    //Log.debug("Class " + testerName + " not found");
0332:                } catch (ClassCastException cce) {
0333:                    throw new BugReport("Class loader conflict: environment "
0334:                            + ComponentTester.class.getClassLoader() + " vs. "
0335:                            + testerClass.getClassLoader());
0336:                }
0337:
0338:                return tester;
0339:            }
0340:
0341:            /** Derive a tag from the given accessible context if possible, or return
0342:             * null.
0343:             */
0344:            protected String deriveAccessibleTag(AccessibleContext context) {
0345:                String tag = null;
0346:                if (context != null) {
0347:                    if (context.getAccessibleName() != null) {
0348:                        tag = context.getAccessibleName();
0349:                    }
0350:                    if ((tag == null || "".equals(tag))
0351:                            && context.getAccessibleIcon() != null
0352:                            && context.getAccessibleIcon().length > 0) {
0353:                        AccessibleIcon[] icons = context.getAccessibleIcon();
0354:                        tag = icons[0].getAccessibleIconDescription();
0355:                        if (tag != null) {
0356:                            tag = tag.substring(tag.lastIndexOf("/") + 1);
0357:                            tag = tag.substring(tag.lastIndexOf("\\") + 1);
0358:                        }
0359:                    }
0360:                }
0361:                return tag;
0362:            }
0363:
0364:            /** Default methods to use to derive a component-specific tag.  These are
0365:             * things that will probably be useful in a custom component if the method
0366:             * is supported.
0367:             */
0368:            private static final String[] tagMethods = { "getLabel",
0369:                    "getTitle", "getText", };
0370:
0371:            /** Return a reasonable identifier for the given component.
0372:                Note that this should not duplicate information provided by existing
0373:                attributes such as title, label, or text.
0374:                This functionality is provided to assist in identification of
0375:                non-standard GUI components only.
0376:             */
0377:            public static String getTag(Component comp) {
0378:                return getTester(comp.getClass()).deriveTag(comp);
0379:            }
0380:
0381:            /** Returns whether the given class is not a core JRE class. */
0382:            protected boolean isCustom(Class c) {
0383:                return !(c.getName().startsWith("javax.swing.") || c.getName()
0384:                        .startsWith("java.awt."));
0385:            }
0386:
0387:            /** Determine a component-specific identifier not already defined in other
0388:             * component attributes.  This method should be defined to something
0389:             * unique for custom UI components.
0390:             */
0391:            public String deriveTag(Component comp) {
0392:                // If the component class is custom, don't provide a tag
0393:                if (isCustom(comp.getClass()))
0394:                    return null;
0395:
0396:                Method m;
0397:                String tag = null;
0398:                // Try a few default methods
0399:                for (int i = 0; i < tagMethods.length; i++) {
0400:                    // Don't use getText on text components
0401:                    if (((comp instanceof  javax.swing.text.JTextComponent) || (comp instanceof  java.awt.TextComponent))
0402:                            && "getText".equals(tagMethods[i])) {
0403:                        continue;
0404:                    }
0405:                    try {
0406:                        m = comp.getClass().getMethod(tagMethods[i], null);
0407:                        String tmp = (String) m.invoke(comp, null);
0408:                        // Don't ever use empty strings for tags
0409:                        if (tmp != null && !"".equals(tmp)) {
0410:                            tag = tmp;
0411:                            break;
0412:                        }
0413:                    } catch (Exception e) {
0414:                    }
0415:                }
0416:                // In the absence of any other tag, try to derive one from something
0417:                // recognizable on one of its ancestors.
0418:                if (tag == null || "".equals(tag)) {
0419:                    Component parent = comp.getParent();
0420:                    if (parent != null) {
0421:                        String ptag = getTag(parent);
0422:                        if (ptag != null && !"".equals(tag)) {
0423:                            // Don't use the tag if it's simply the window title; that
0424:                            // doesn't provide any extra information.
0425:                            if (!ptag.endsWith(" Root Pane")) {
0426:                                StringBuffer buf = new StringBuffer(ptag);
0427:                                int under = ptag.indexOf(" under ");
0428:                                if (under != -1)
0429:                                    buf = buf.delete(0, under + 7);
0430:                                buf.insert(0, " under ");
0431:                                buf.insert(0, simpleClassName(comp.getClass()));
0432:                                tag = buf.toString();
0433:                            }
0434:                        }
0435:                    }
0436:                }
0437:
0438:                return tag;
0439:            }
0440:
0441:            /**
0442:             * Wait for an idle AWT event queue.  Will return when there are no more
0443:             * events on the event queue.
0444:             */
0445:            public void actionWaitForIdle() {
0446:                waitForIdle();
0447:            }
0448:
0449:            /** Delay the given number of ms. */
0450:            public void actionDelay(int ms) {
0451:                delay(ms);
0452:            }
0453:
0454:            /** @deprecated  Renamed to {@link #actionSelectAWTMenuItem(Frame,String)}.
0455:             */
0456:            public void actionSelectAWTMenuItemByLabel(Frame menuFrame,
0457:                    String path) {
0458:                actionSelectAWTMenuItem(menuFrame, path);
0459:            }
0460:
0461:            /** Selects an AWT menu item ({@link java.awt.MenuItem}) and returns when
0462:                the invocation has triggered (though not necessarily completed).  
0463:                @param menuFrame
0464:                @param path either a unique label or the menu path.
0465:                @see Robot#selectAWTMenuItem(Frame,String)
0466:             */
0467:            public void actionSelectAWTMenuItem(Frame menuFrame, String path) {
0468:                AWTMenuListener listener = new AWTMenuListener();
0469:                new WeakAWTEventListener(listener,
0470:                        ActionEvent.ACTION_EVENT_MASK);
0471:                selectAWTMenuItem(menuFrame, path);
0472:                long start = System.currentTimeMillis();
0473:                while (!listener.eventFired) {
0474:                    if (System.currentTimeMillis() - start > defaultDelay) {
0475:                        throw new ActionFailedException("Menu item '" + path
0476:                                + "' failed to fire");
0477:                    }
0478:                    sleep();
0479:                }
0480:                waitForIdle();
0481:            }
0482:
0483:            /** @deprecated  Renamed to
0484:                {@link #actionSelectAWTPopupMenuItem(Component,String)}.
0485:             */
0486:            public void actionSelectAWTPopupMenuItemByLabel(Component invoker,
0487:                    String path) {
0488:                actionSelectAWTPopupMenuItem(invoker, path);
0489:            }
0490:
0491:            /** Selects an AWT menu item and returns when the invocation has triggered
0492:                (though not necessarily completed).
0493:                @see Robot#selectAWTPopupMenuItem(Component,String)
0494:             */
0495:            public void actionSelectAWTPopupMenuItem(Component invoker,
0496:                    String path) {
0497:                AWTMenuListener listener = new AWTMenuListener();
0498:                new WeakAWTEventListener(listener,
0499:                        ActionEvent.ACTION_EVENT_MASK);
0500:                selectAWTPopupMenuItem(invoker, path);
0501:                long start = System.currentTimeMillis();
0502:                while (!listener.eventFired) {
0503:                    if (System.currentTimeMillis() - start > defaultDelay) {
0504:                        throw new ActionFailedException("Menu item '" + path
0505:                                + "' failed to fire");
0506:                    }
0507:                    sleep();
0508:                }
0509:                waitForIdle();
0510:            }
0511:
0512:            /** Select the given menu item. */
0513:            public void actionSelectMenuItem(Component item) {
0514:                Log.debug("Attempting to select menu item " + toString(item));
0515:                selectMenuItem(item);
0516:                waitForIdle();
0517:            }
0518:
0519:            /** Select the given menu item, given its path and a component on the same
0520:                window.
0521:             */
0522:            public void actionSelectMenuItem(Component sameWindow, String path) {
0523:                Log.debug("Attempting to select menu item '" + path + "'");
0524:                selectMenuItem(sameWindow, path);
0525:                waitForIdle();
0526:            }
0527:
0528:            /** Pop up a menu at the center of the given component and
0529:                select the given item.
0530:             */
0531:            public void actionSelectPopupMenuItem(Component invoker, String path) {
0532:                actionSelectPopupMenuItem(invoker, invoker.getWidth() / 2,
0533:                        invoker.getHeight() / 2, path);
0534:            }
0535:
0536:            /** Pop up a menu at the given location on the given component and
0537:                select the given item.
0538:             */
0539:            public void actionSelectPopupMenuItem(Component invoker,
0540:                    ComponentLocation loc, String path) {
0541:                selectPopupMenuItem(invoker, loc, path);
0542:                waitForIdle();
0543:            }
0544:
0545:            /** Pop up a menu at the given coordinates on the given component and
0546:                select the given item.
0547:             */
0548:            public void actionSelectPopupMenuItem(Component invoker, int x,
0549:                    int y, String path) {
0550:                actionSelectPopupMenuItem(invoker, new ComponentLocation(
0551:                        new Point(x, y)), path);
0552:            }
0553:
0554:            /** Pop up a menu in the center of the given component. */
0555:            public void actionShowPopupMenu(Component invoker) {
0556:                actionShowPopupMenu(invoker, new ComponentLocation());
0557:            }
0558:
0559:            /** Pop up a menu in the center of the given component. */
0560:            public void actionShowPopupMenu(Component invoker,
0561:                    ComponentLocation loc) {
0562:                Point where = loc.getPoint(invoker);
0563:                showPopupMenu(invoker, where.x, where.y);
0564:            }
0565:
0566:            /** Pop up a menu at the given location on the given component. 
0567:             */
0568:            public void actionShowPopupMenu(Component invoker, int x, int y) {
0569:                showPopupMenu(invoker, x, y);
0570:            }
0571:
0572:            /** Click on the center of the component. */
0573:            public void actionClick(Component comp) {
0574:                actionClick(comp, new ComponentLocation());
0575:            }
0576:
0577:            /** Click on the component at the given location. */
0578:            public void actionClick(Component c, ComponentLocation loc) {
0579:                actionClick(c, loc, InputEvent.BUTTON1_MASK);
0580:            }
0581:
0582:            /** Click on the component at the given location with the given
0583:                modifiers.
0584:             */
0585:            public void actionClick(Component c, ComponentLocation loc,
0586:                    int buttons) {
0587:                actionClick(c, loc, buttons, 1);
0588:            }
0589:
0590:            /** Click on the component at the given location, with the given
0591:             * modifiers and click count.
0592:             */
0593:            public void actionClick(Component c, ComponentLocation loc,
0594:                    int buttons, int count) {
0595:                Point where = loc.getPoint(c);
0596:                click(c, where.x, where.y, buttons, count);
0597:                waitForIdle();
0598:            }
0599:
0600:            /** Click on the component at the given location (mouse button 1).
0601:             */
0602:            public void actionClick(Component comp, int x, int y) {
0603:                actionClick(comp, new ComponentLocation(new Point(x, y)));
0604:            }
0605:
0606:            /** Click on the component at the given location.  The buttons mask
0607:             * should be the InputEvent masks for the desired button, e.g.
0608:             * {@link InputEvent#BUTTON1_MASK}.  ComponentTester also defines
0609:             * {@link AWTConstants#POPUP_MASK} and {@link AWTConstants#TERTIARY_MASK} for
0610:             * platform-independent masks for those buttons.  Key modifiers other
0611:             * than {@link InputEvent#ALT_MASK} and {@link InputEvent#META_MASK} may
0612:             * also be used as a convenience.
0613:             */
0614:            public void actionClick(Component comp, int x, int y, int buttons) {
0615:                actionClick(comp, x, y, buttons, 1);
0616:            }
0617:
0618:            /** Click on the component at the given location, specifying buttons and
0619:             * the number of clicks.  The buttons mask should be the InputEvent mask
0620:             * for the desired button, e.g. 
0621:             * {@link InputEvent#BUTTON1_MASK}.  ComponentTester also defines
0622:             * {@link AWTConstants#POPUP_MASK} and {@link AWTConstants#TERTIARY_MASK} for
0623:             * platform-independent masks for those buttons.  Key modifiers other
0624:             * than {@link InputEvent#ALT_MASK} and {@link InputEvent#META_MASK} may
0625:             * also be used as a convenience.
0626:             */
0627:            public void actionClick(Component comp, int x, int y, int buttons,
0628:                    int count) {
0629:                actionClick(comp, new ComponentLocation(new Point(x, y)),
0630:                        buttons, count);
0631:            }
0632:
0633:            /** Send a key press event for the given virtual key code to the given
0634:                Component.
0635:             */
0636:            public void actionKeyPress(Component comp, int keyCode) {
0637:                actionFocus(comp);
0638:                actionKeyPress(keyCode);
0639:            }
0640:
0641:            /** Generate a key press event for the given virtual key code. */
0642:            public void actionKeyPress(int keyCode) {
0643:                keyPress(keyCode);
0644:                waitForIdle();
0645:            }
0646:
0647:            /** Generate a key release event sent to the given component. */
0648:            public void actionKeyRelease(Component comp, int keyCode) {
0649:                actionFocus(comp);
0650:                actionKeyRelease(keyCode);
0651:            }
0652:
0653:            /** Generate a key release event. */
0654:            public void actionKeyRelease(int keyCode) {
0655:                keyRelease(keyCode);
0656:                waitForIdle();
0657:            }
0658:
0659:            /** Set the state of the given modifier keys. */
0660:            public void actionSetModifiers(int mask, boolean pressed) {
0661:                setModifiers(mask, pressed);
0662:                waitForIdle();
0663:            }
0664:
0665:            /**
0666:             * Send the given keystroke, which must be the KeyEvent field name of a
0667:             * KeyEvent VK_ constant to the program.  Sends a key down/up, with no
0668:             * modifiers.  The focus is changed to the target component.
0669:             */
0670:            public void actionKeyStroke(Component c, int keyCode) {
0671:                actionFocus(c);
0672:                actionKeyStroke(keyCode, 0);
0673:            }
0674:
0675:            /** 
0676:             * Send the given keystroke, which must be the KeyEvent field name of a
0677:             * KeyEvent VK_ constant.  Sends a key press and key release, with no 
0678:             * modifiers.  Note that this method does not affect the current focus.
0679:             */
0680:            public void actionKeyStroke(int keyCode) {
0681:                actionKeyStroke(keyCode, 0);
0682:            }
0683:
0684:            /**
0685:             * Send the given keystroke, which must be the KeyEvent field name of a
0686:             * KeyEvent VK_ constant to the program.  Sends a key down/up, with the
0687:             * given modifiers, which should be the InputEvent field name modifier
0688:             * masks optionally ORed together with "|".  The focus is changed to the
0689:             * target component.<p>
0690:             */
0691:            public void actionKeyStroke(Component c, int keyCode, int modifiers) {
0692:                actionFocus(c);
0693:                actionKeyStroke(keyCode, modifiers);
0694:            }
0695:
0696:            /**
0697:             * Send the given keystroke, which must be the KeyEvent field name of a
0698:             * KeyEvent VK_ constant to the program.  Sends a key down/up, with the
0699:             * given modifiers, which should be the InputEvent field name modifier
0700:             * masks optionally ORed together with "|".  Note that this does not
0701:             * affect the current focus.<p>
0702:             */
0703:            public void actionKeyStroke(int keyCode, int modifiers) {
0704:                if (Bugs.hasKeyStrokeGenerationBug()) {
0705:                    int oldDelay = getAutoDelay();
0706:                    setAutoDelay(50);
0707:                    key(keyCode, modifiers);
0708:                    setAutoDelay(oldDelay);
0709:                    delay(100);
0710:                } else {
0711:                    key(keyCode, modifiers);
0712:                }
0713:                waitForIdle();
0714:            }
0715:
0716:            /** Send events required to generate the given string on the given
0717:             * component.  This version is preferred over
0718:             * {@link #actionKeyString(String)}.
0719:             */
0720:            public void actionKeyString(Component c, String string) {
0721:                actionFocus(c);
0722:                actionKeyString(string);
0723:            }
0724:
0725:            /** Send events required to generate the given string. */
0726:            public void actionKeyString(String string) {
0727:                keyString(string);
0728:                // FIXME waitForIdle isn't always sufficient on OSX with key events
0729:                if (Bugs.hasKeyStrokeGenerationBug()) {
0730:                    delay(100);
0731:                }
0732:                waitForIdle();
0733:            }
0734:
0735:            /** Set the focus on to the given component. */
0736:            public void actionFocus(Component comp) {
0737:                focus(comp, true);
0738:            }
0739:
0740:            /** Move the mouse/pointer to the given location. */
0741:            public void actionMouseMove(Component comp, ComponentLocation loc) {
0742:                Point where = loc.getPoint(comp);
0743:                mouseMove(comp, where.x, where.y);
0744:                waitForIdle();
0745:            }
0746:
0747:            /** Press mouse button 1 at the given location. */
0748:            public void actionMousePress(Component comp, ComponentLocation loc) {
0749:                actionMousePress(comp, loc, InputEvent.BUTTON1_MASK);
0750:            }
0751:
0752:            /** Press mouse buttons corresponding to the given mask at the given
0753:                location.
0754:             */
0755:            public void actionMousePress(Component comp, ComponentLocation loc,
0756:                    int mask) {
0757:                Point where = loc.getPoint(comp);
0758:                mousePress(comp, where.x, where.y, mask);
0759:                waitForIdle();
0760:            }
0761:
0762:            /** Release any currently held mouse buttons. */
0763:            public void actionMouseRelease() {
0764:                mouseRelease();
0765:                waitForIdle();
0766:            }
0767:
0768:            /** Perform a drag action.  Derived classes may provide more specific
0769:             * identifiers for what is being dragged simply by deriving a new class
0770:             * from ComponentLocation which identifies the appropriate substructure.
0771:             * For instance, a {@link JTreeLocation} might encapsulate the expansion
0772:             * control location for the path [root, node A, child B].
0773:             */
0774:            public void actionDrag(Component dragSource, ComponentLocation loc) {
0775:                actionDrag(dragSource, loc, "BUTTON1_MASK");
0776:            }
0777:
0778:            /** Perform a drag action.  Grabs the center of the given component. */
0779:            public void actionDrag(Component dragSource) {
0780:                actionDrag(dragSource, new ComponentLocation());
0781:            }
0782:
0783:            /** Perform a drag action with the given modifiers.  
0784:             * @param dragSource source of the drag
0785:             * @param loc identifies where on the given {@link Component} to begin the
0786:             * drag.
0787:             * @param buttons a <code>String</code> representation of key modifiers,
0788:             * e.g. "ALT|SHIFT", based on the {@link InputEvent#ALT_MASK InputEvent
0789:             * <code>_MASK</code> fields}.
0790:             * @deprecated Use the
0791:             * {@link #actionDrag(Component,ComponentLocation,int) integer modifier mask} 
0792:             * version instead.
0793:             */
0794:            public void actionDrag(Component dragSource, ComponentLocation loc,
0795:                    String buttons) {
0796:                actionDrag(dragSource, loc, AWT.getModifiers(buttons));
0797:            }
0798:
0799:            /** Perform a drag action with the given modifiers.  
0800:             * @param dragSource source of the drag
0801:             * @param loc identifies where on the given {@link Component} to begin the
0802:             * drag.
0803:             * @param buttons one or more of the 
0804:             * {@link InputEvent#BUTTON1_MASK InputEvent <code>BUTTONN_MASK</code> 
0805:             * fields}.
0806:             */
0807:            public void actionDrag(Component dragSource, ComponentLocation loc,
0808:                    int buttons) {
0809:                Point where = loc.getPoint(dragSource);
0810:                drag(dragSource, where.x, where.y, buttons);
0811:                waitForIdle();
0812:            }
0813:
0814:            /** Perform a drag action.  Grabs at the given explicit location. */
0815:            public void actionDrag(Component dragSource, int sx, int sy) {
0816:                actionDrag(dragSource, new ComponentLocation(new Point(sx, sy)));
0817:            }
0818:
0819:            /** Perform a drag action.  Grabs at the given location with the given
0820:             * modifiers.
0821:             * @param dragSource source of the drag
0822:             * @param sx X coordinate
0823:             * @param sy Y coordinate
0824:             * @param buttons a <code>String</code> representation of key modifiers,
0825:             * e.g. "ALT|SHIFT", based on the {@link InputEvent#ALT_MASK InputEvent
0826:             * <code>_MASK</code> fields}.
0827:             * @deprecated Use the
0828:             * {@link #actionDrag(Component,ComponentLocation,int) ComponentLocation/
0829:             * integer modifier mask} version instead.
0830:             */
0831:            public void actionDrag(Component dragSource, int sx, int sy,
0832:                    String buttons) {
0833:                actionDrag(dragSource,
0834:                        new ComponentLocation(new Point(sx, sy)), buttons);
0835:            }
0836:
0837:            /** Drag the current dragged object over the given component. */
0838:            public void actionDragOver(Component target) {
0839:                actionDragOver(target, new ComponentLocation());
0840:            }
0841:
0842:            /** Drag the current dragged object over the given target/location. */
0843:            public void actionDragOver(Component target, ComponentLocation where) {
0844:                Point loc = where.getPoint(target);
0845:                dragOver(target, loc.x, loc.y);
0846:                waitForIdle();
0847:            }
0848:
0849:            /** Perform a basic drop action (implicitly causing preceding mouse
0850:             * drag motion).  Drops in the center of the component.
0851:             */
0852:            public void actionDrop(Component dropTarget) {
0853:                actionDrop(dropTarget, new ComponentLocation());
0854:            }
0855:
0856:            /** Perform a basic drop action (implicitly causing preceding mouse
0857:             * drag motion).
0858:             */
0859:            public void actionDrop(Component dropTarget, ComponentLocation loc) {
0860:                Point where = loc.getPoint(dropTarget);
0861:                drop(dropTarget, where.x, where.y);
0862:                waitForIdle();
0863:            }
0864:
0865:            /** Perform a basic drop action (implicitly causing preceding mouse
0866:             * drag motion).  The modifiers represents the set of active modifiers
0867:             * when the drop is made.
0868:             */
0869:            public void actionDrop(Component dropTarget, int x, int y) {
0870:                drop(dropTarget, x, y);
0871:                waitForIdle();
0872:            }
0873:
0874:            /** Return whether the component's contents matches the given image. */
0875:            public boolean assertImage(Component comp, java.io.File fileImage,
0876:                    boolean ignoreBorder) {
0877:                java.awt.image.BufferedImage img = capture(comp, ignoreBorder);
0878:                return new ImageComparator().compare(img, fileImage) == 0;
0879:            }
0880:
0881:            /** Returns whether a Window corresponding to the given String is
0882:             * showing.  The string may be a plain String or regular expression and
0883:             * may match either the window title (for Frames or Dialogs) or the
0884:             * value of {@link Component#getName}. 
0885:             */
0886:            public boolean assertFrameShowing(Hierarchy h, String id) {
0887:                try {
0888:                    ComponentFinder finder = new BasicFinder(h);
0889:                    return finder.find(new WindowMatcher(id, true)) != null;
0890:                } catch (ComponentNotFoundException e) {
0891:                    return false;
0892:                } catch (MultipleComponentsFoundException m) {
0893:                    // Might not be the one you want, but that's what the docs say
0894:                    return true;
0895:                }
0896:            }
0897:
0898:            /** Returns whether a Window corresponding to the given String is
0899:             * showing.  The string may be a plain String or regular expression and
0900:             * may match either the window title (for Frames or Dialogs) or the value
0901:             * of {@link Component#getName}. 
0902:             * @deprecated This method does not specify the proper context for the
0903:             * lookup.  Use {@link #assertFrameShowing(Hierarchy,String)} instead. 
0904:             */
0905:            public boolean assertFrameShowing(String id) {
0906:                return assertFrameShowing(AWTHierarchy.getDefault(), id);
0907:            }
0908:
0909:            /** Convenience wait for a window to be displayed.  The given string may
0910:             * be a plain String or regular expression and may match either the window
0911:             * title (for Frames and Dialogs) or the value of {@link Component#getName}.
0912:             * This method is provided as a convenience for hand-coded tests, since 
0913:             * scripts will use a wait step instead.<p>
0914:             * The property <code>abbot.robot.component_delay</code> affects the 
0915:             * default timeout.
0916:             */
0917:            public void waitForFrameShowing(final Hierarchy h,
0918:                    final String identifier) {
0919:                wait(new Condition() {
0920:                    public boolean test() {
0921:                        return assertFrameShowing(h, identifier);
0922:                    }
0923:
0924:                    public String toString() {
0925:                        return Strings.get("tester.Component.show_wait",
0926:                                new Object[] { identifier });
0927:                    }
0928:                }, componentDelay);
0929:            }
0930:
0931:            /** Convenience wait for a window to be displayed.  The given string may
0932:             * be a plain String or regular expression and may match either the window
0933:             * title (for Frames and Dialogs) or the value of {@link Component#getName}. 
0934:             * This method is provided as a convenience for hand-coded tests, since 
0935:             * scripts will use a wait step instead.<p>
0936:             * The property abbot.robot.component_delay affects the default timeout.
0937:             * @deprecated This method does not provide sufficient context to reliably
0938:             * find a component.  Use {@link #waitForFrameShowing(Hierarchy,String)} 
0939:             * instead. 
0940:             */
0941:            public void waitForFrameShowing(final String identifier) {
0942:                waitForFrameShowing(AWTHierarchy.getDefault(), identifier);
0943:            }
0944:
0945:            /** Return whether the Component represented by the given
0946:                ComponentReference is available.
0947:             */
0948:            public boolean assertComponentShowing(ComponentReference ref) {
0949:                try {
0950:                    Component c = ref.getComponent();
0951:                    return isReadyForInput(c);
0952:                } catch (ComponentSearchException e) {
0953:                    return false;
0954:                }
0955:            }
0956:
0957:            /** Wait for the Component represented by the given ComponentReference to
0958:                become available.  The timeout is affected by
0959:                abbot.robot.component_delay, which defaults to 30s. 
0960:             */
0961:            public void waitForComponentShowing(final ComponentReference ref) {
0962:                wait(new Condition() {
0963:                    public boolean test() {
0964:                        return assertComponentShowing(ref);
0965:                    }
0966:
0967:                    public String toString() {
0968:                        return Strings.get("tester.Component.show_wait",
0969:                                new Object[] { ref });
0970:                    }
0971:                }, componentDelay);
0972:            }
0973:
0974:            private Method[] cachedMethods = null;
0975:
0976:            /** Look up methods with the given prefix.  Facilitates auto-scanning by
0977:             * scripts and the script editor.
0978:             */
0979:            private Method[] getMethods(String prefix, Class returnType,
0980:                    boolean componentArgument) {
0981:                if (cachedMethods == null) {
0982:                    cachedMethods = getClass().getMethods();
0983:                }
0984:                ArrayList methods = new ArrayList();
0985:                // Only save one Method for each unique name
0986:                HashSet names = new HashSet(IGNORED_METHODS);
0987:
0988:                Method[] mlist = cachedMethods;
0989:                for (int i = 0; i < mlist.length; i++) {
0990:                    String name = mlist[i].getName();
0991:                    if (names.contains(name) || !name.startsWith(prefix))
0992:                        continue;
0993:                    Class[] params = mlist[i].getParameterTypes();
0994:                    if ((returnType == null || returnType.equals(mlist[i]
0995:                            .getReturnType()))
0996:                            && ((params.length == 0 && !componentArgument) || (params.length > 0 && (Component.class
0997:                                    .isAssignableFrom(params[0]) == componentArgument)))) {
0998:                        methods.add(mlist[i]);
0999:                        names.add(name);
1000:                    }
1001:                }
1002:                return (Method[]) methods.toArray(new Method[methods.size()]);
1003:            }
1004:
1005:            private Method[] cachedActions = null;
1006:
1007:            /** Return a list of all actions defined by this class that don't depend
1008:             * on a component argument.
1009:             */
1010:            public Method[] getActions() {
1011:                if (cachedActions == null) {
1012:                    cachedActions = getMethods("action", void.class, false);
1013:                }
1014:                return cachedActions;
1015:            }
1016:
1017:            private Method[] cachedComponentActions = null;
1018:
1019:            /** Return a list of all actions defined by this class that require
1020:             * a component argument.
1021:             */
1022:            public Method[] getComponentActions() {
1023:                if (cachedComponentActions == null) {
1024:                    cachedComponentActions = getMethods("action", void.class,
1025:                            true);
1026:                }
1027:                return cachedComponentActions;
1028:            }
1029:
1030:            private Method[] cachedPropertyMethods = null;
1031:
1032:            /** Return an array of all property check methods defined by this class.
1033:             * The first argument <b>must</b> be a Component.
1034:             */
1035:            public Method[] getPropertyMethods() {
1036:                if (cachedPropertyMethods == null) {
1037:                    ArrayList all = new ArrayList();
1038:                    all.addAll(Arrays.asList(getMethods("is", boolean.class,
1039:                            true)));
1040:                    all.addAll(Arrays.asList(getMethods("has", boolean.class,
1041:                            true)));
1042:                    all.addAll(Arrays.asList(getMethods("get", null, true)));
1043:                    cachedPropertyMethods = (Method[]) all
1044:                            .toArray(new Method[all.size()]);
1045:                }
1046:                return cachedPropertyMethods;
1047:            }
1048:
1049:            private Method[] cachedAssertMethods = null;
1050:
1051:            /** Return a list of all assertions defined by this class that don't
1052:             * depend on a component argument.
1053:             */
1054:            public Method[] getAssertMethods() {
1055:                if (cachedAssertMethods == null) {
1056:                    cachedAssertMethods = getMethods("assert", boolean.class,
1057:                            false);
1058:                }
1059:                return cachedAssertMethods;
1060:            }
1061:
1062:            private Method[] cachedComponentAssertMethods = null;
1063:
1064:            /** Return a list of all assertions defined by this class that require a
1065:             * component argument.
1066:             */
1067:            public Method[] getComponentAssertMethods() {
1068:                if (cachedComponentAssertMethods == null) {
1069:                    cachedComponentAssertMethods = getMethods("assert",
1070:                            boolean.class, true);
1071:                }
1072:                return cachedComponentAssertMethods;
1073:            }
1074:
1075:            /** Quick and dirty strip raw text from html, for getting the basic text
1076:                from html-formatted labels and buttons.  Behavior is undefined for
1077:                badly formatted html.
1078:             */
1079:            public static String stripHTML(String str) {
1080:                if (str != null
1081:                        && (str.startsWith("<html>") || str
1082:                                .startsWith("<HTML>"))) {
1083:                    while (str.startsWith("<")) {
1084:                        int right = str.indexOf(">");
1085:                        if (right == -1)
1086:                            break;
1087:                        str = str.substring(right + 1);
1088:                    }
1089:                    while (str.endsWith(">")) {
1090:                        int right = str.lastIndexOf("<");
1091:                        if (right == -1)
1092:                            break;
1093:                        str = str.substring(0, right);
1094:                    }
1095:                }
1096:                return str;
1097:            }
1098:
1099:            /** Wait for the given condition, throwing an ActionFailedException if it
1100:             * times out.
1101:             */
1102:            protected void waitAction(String desc, Condition cond)
1103:                    throws ActionFailedException {
1104:                try {
1105:                    wait(cond);
1106:                } catch (WaitTimedOutError wto) {
1107:                    throw new ActionFailedException(desc);
1108:                }
1109:            }
1110:
1111:            /** Return the Component class that corresponds to this 
1112:             * <tt>ComponentTester</tt>
1113:             * class.  For example, 
1114:             * <tt>JComponentTester.getTestedClass(JLabel.class)</tt>
1115:             * would return <tt>JComponent.class</tt>.
1116:             */
1117:            public Class getTestedClass(Class cls) {
1118:                while (getTester(cls.getSuperclass()) == this ) {
1119:                    cls = cls.getSuperclass();
1120:                }
1121:                return cls;
1122:            }
1123:
1124:            /** Parse the String representation of a <tt>ComponentLocation</tt> into 
1125:             * the actual <tt>ComponentLocation</tt> object.
1126:             */
1127:            public ComponentLocation parseLocation(String encoded) {
1128:                return new ComponentLocation().parse(encoded);
1129:            }
1130:
1131:            /** Return a ComponentLocation for the given Point.  Derived classes may
1132:             * provide something more suitable than an (x, y) coordinate.  A 
1133:             * {@link javax.swing.JTree}, for example, might provide a 
1134:             * {@link JTreeLocation} 
1135:             * indicating a path or row in the tree.
1136:             */
1137:            public ComponentLocation getLocation(Component c, Point where) {
1138:                return new ComponentLocation(where);
1139:            }
1140:
1141:            private class AWTMenuListener implements  AWTEventListener {
1142:                public volatile boolean eventFired;
1143:
1144:                public void eventDispatched(AWTEvent e) {
1145:                    if (e.getID() == ActionEvent.ACTION_PERFORMED) {
1146:                        eventFired = true;
1147:                    }
1148:                }
1149:            }
1150:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.