Source Code Cross Referenced for AWTFixtureHelper.java in  » Testing » abbot-1.0.1 » abbot » util » 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.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package abbot.util;
002:
003:        import java.awt.AWTEvent;
004:        import java.awt.Component;
005:        import java.awt.Dialog;
006:        import java.awt.Dimension;
007:        import java.awt.EventQueue;
008:        import java.awt.Frame;
009:        import java.awt.Window;
010:        import java.awt.event.*;
011:        import java.util.Iterator;
012:        import javax.swing.JFrame;
013:        import javax.swing.JPanel;
014:        import javax.swing.JPopupMenu;
015:        import javax.swing.SwingUtilities;
016:        import javax.swing.border.EmptyBorder;
017:
018:        import abbot.Log;
019:        import abbot.finder.BasicFinder;
020:        import abbot.finder.ComponentFinder;
021:        import abbot.finder.ComponentNotFoundException;
022:        import abbot.finder.ComponentSearchException;
023:        import abbot.finder.Hierarchy;
024:        import abbot.finder.Matcher;
025:        import abbot.finder.MultipleComponentsFoundException;
026:        import abbot.finder.TestHierarchy;
027:        import abbot.finder.matchers.ClassMatcher;
028:        import abbot.finder.matchers.WindowMatcher;
029:        import abbot.tester.Robot;
030:        import abbot.tester.WindowTracker;
031:
032:        /** Provides various facilities for setting up, using, and tearing down
033:         * a test involving UI components.
034:         * Handles standardized AWTEvent logging and catching exceptions on the
035:         * AWT event dispatch thread (EDT).
036:         * This class should be used at setup and teardown of your chosen fixture.
037:         * @see junit.extensions.abbot.ComponentTestFixture
038:         * @see abbot.script.StepRunner  
039:         */
040:
041:        public class AWTFixtureHelper {
042:            /** Typical delay to wait for a robot event to be translated into a Java
043:            event. */
044:            public static final int EVENT_GENERATION_DELAY = 5000;
045:            public static final int WINDOW_DELAY = 20000; // for slow systems
046:            public static final int POPUP_DELAY = 10000;
047:
048:            private AWTEventListener listener = null;
049:            private SystemState state;
050:            private Robot robot;
051:            private WindowTracker tracker;
052:            private Hierarchy hierarchy;
053:            // modifiers set during this helper's lifetime (to be cleared on dispose)
054:            private int modifiers;
055:
056:            public AWTFixtureHelper() {
057:                this (new TestHierarchy());
058:            }
059:
060:            /** Create an instance of AWTFixtureHelper which makes a snapshot of the
061:                current VM state.
062:             */
063:            public AWTFixtureHelper(Hierarchy hierarchy) {
064:                // Preserve all system properties to restore them later
065:                state = new SystemState();
066:                this .hierarchy = hierarchy;
067:
068:                // Install our own event handler, which will forward events thrown on
069:                // the event queue
070:                try {
071:                    new EDTExceptionCatcher().install();
072:                } catch (RuntimeException re) {
073:                    // Not fatal if we can't install, since most tests don't
074:                    // depend on it.  We won't be able to throw errors that were
075:                    // generated on the event dispatch thread, though.
076:                }
077:                // Only enable event logging if debug is enabled for this class
078:                // Facilitate debugging by logging all events
079:                if (Boolean.getBoolean("abbot.fixture.log_events")) {
080:                    long mask = Properties
081:                            .getProperty(
082:                                    "abbot.fixture.event_mask",
083:                                    Long.MIN_VALUE,
084:                                    Long.MAX_VALUE,
085:                                    abbot.editor.recorder.EventRecorder.RECORDING_EVENT_MASK);
086:
087:                    Log.log("Using mask value " + mask);
088:                    listener = new AWTEventListener() {
089:                        public void eventDispatched(AWTEvent event) {
090:                            if (listener != null)
091:                                Log.log(Robot.toString(event));
092:                        }
093:                    };
094:                    new WeakAWTEventListener(listener, mask);
095:                }
096:                robot = new Robot();
097:                tracker = WindowTracker.getTracker();
098:
099:                SystemState.clearLockingKeys();
100:                robot.reset();
101:                if (Bugs.hasMultiClickFrameBug())
102:                    robot.delay(500);
103:            }
104:
105:            public Robot getRobot() {
106:                return robot;
107:            }
108:
109:            public WindowTracker getWindowTracker() {
110:                return tracker;
111:            }
112:
113:            public Hierarchy getHierarchy() {
114:                return hierarchy;
115:            }
116:
117:            /** Returns the last exception thrown on the event dispatch thread, or
118:                <code>null</code> if no such exception has been thrown.
119:             */
120:            public Throwable getEventDispatchError() {
121:                return EDTExceptionCatcher.getThrowable();
122:            }
123:
124:            /** Returns the time of the last exception thrown on the event dispatch
125:                thread.
126:             */
127:            public long getEventDispatchErrorTime() {
128:                return EDTExceptionCatcher.getThrowableTime();
129:            }
130:
131:            /** Convenience method to set key modifiers.  Using this method is 
132:             * preferred to invoking {@link Robot#setModifiers(int,boolean)} or 
133:             * {@link Robot#keyPress(int)}, since this method's effects will be 
134:             * automatically undone at the end of the test.  If you use the 
135:             * {@link Robot} methods, you must remember to release any keys pressed 
136:             * during the test.
137:             * @param modifiers mask indicating which modifier keys to use
138:             * @param pressed whether the modifiers should be in the pressed state.
139:             */
140:            public void setModifiers(int modifiers, boolean pressed) {
141:                if (pressed)
142:                    this .modifiers |= modifiers;
143:                else
144:                    this .modifiers &= ~modifiers;
145:                robot.setModifiers(modifiers, pressed);
146:                robot.waitForIdle();
147:            }
148:
149:            protected void disposeAll() {
150:                Iterator iter = hierarchy.getRoots().iterator();
151:                while (iter.hasNext()) {
152:                    hierarchy.dispose((Window) iter.next());
153:                }
154:            }
155:
156:            /** Restore the state that was preserved when this object was created.
157:             */
158:            public void restore() {
159:                if (AWT.isAWTPopupMenuBlocking())
160:                    AWT.dismissAWTPopup();
161:                state.restore();
162:
163:                // Encourage GC of unused components, which reduces the load on
164:                // future tests.
165:                System.gc();
166:                System.runFinalization();
167:            }
168:
169:            /** Dispose all windows created during this object's lifetime and restore
170:             * the previous system/UI state, to the extent possible.
171:             */
172:            public void dispose() {
173:                // WARNING: clear input state prior to disposing windows,
174:                // otherwise native drag operations may be left stuck
175:                if (robot != null) {
176:                    if (modifiers != 0) {
177:                        robot.setModifiers(modifiers, false);
178:                        modifiers = 0;
179:                    }
180:                    int buttons = Robot.getState().getButtons();
181:                    if (buttons != 0) {
182:                        Log.debug("release " + AWT.getMouseModifiers(buttons));
183:                        robot.mouseRelease(buttons);
184:                    }
185:                    if (robot.getState().isNativeDragActive()) {
186:                        robot.keyPress(KeyEvent.VK_ESCAPE);
187:                        robot.keyRelease(KeyEvent.VK_ESCAPE);
188:                    }
189:                    // TODO: release *any* keys that were pressed, not just modifiers
190:                }
191:                disposeAll();
192:                restore();
193:            }
194:
195:            /** This method should be invoked to display the component under test.
196:             * The frame's size will be its preferred size.  This method will return
197:             * with the enclosing {@link Frame} is showing and ready for input.
198:             */
199:            public Frame showFrame(Component comp) {
200:                return showFrame(comp, null);
201:            }
202:
203:            /** This method should be invoked to display the component under test,
204:             * when a specific size of frame is desired.  The method will return when
205:             * the enclosing {@link Frame} is showing and ready for input.  
206:             * @param comp
207:             * @param size Desired size of the enclosing frame, or <code>null</code>
208:             * to make no explicit adjustments to its size.
209:             */
210:            public Frame showFrame(Component comp, Dimension size) {
211:                return showFrame(comp, size, "Test Frame");
212:            }
213:
214:            /** This method should be invoked to display the component under test,
215:             * when a specific size of frame is desired.  The method will return when
216:             * the enclosing {@link Frame} is showing and ready for input.  
217:             * @param comp
218:             * @param size Desired size of the enclosing frame, or <code>null</code>
219:             * to make no explicit adjustments to its size.
220:             * @param title Title of the wrapping frame
221:             */
222:            public Frame showFrame(Component comp, Dimension size, String title) {
223:                JFrame frame = new JFrame(title);
224:                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
225:                JPanel pane = (JPanel) frame.getContentPane();
226:                pane.setBorder(new EmptyBorder(10, 10, 10, 10));
227:                pane.add(comp);
228:                showWindow(frame, size, true);
229:                return frame;
230:            }
231:
232:            /** Safely display a window with proper EDT synchronization.   This method
233:             * blocks until the {@link Window} is showing and ready for input.
234:             */
235:            public void showWindow(Window w) {
236:                showWindow(w, null, true);
237:            }
238:
239:            /** Safely display a window with proper EDT synchronization.   This method
240:             * blocks until the {@link Window} is showing and ready for input.
241:             */
242:            public void showWindow(final Window w, final Dimension size) {
243:                showWindow(w, size, true);
244:            }
245:
246:            /** Safely display a window with proper EDT synchronization.   This method
247:             * blocks until the window is showing.  This method will return even when
248:             * the window is a modal dialog, since the show method is called on the
249:             * event dispatch thread.  The window will be packed if the pack flag is
250:             * set, and set to the given size if it is non-<code>null</code>.<p>
251:             * Modal dialogs may be shown with this method without blocking.
252:             */
253:            public void showWindow(final Window w, final Dimension size,
254:                    final boolean pack) {
255:                EventQueue.invokeLater(new Runnable() {
256:                    public void run() {
257:                        if (pack) {
258:                            w.pack();
259:                            // Make sure the window is positioned away from
260:                            // any toolbars around the display borders
261:                            w.setLocation(100, 100);
262:                        }
263:                        if (size != null)
264:                            w.setSize(size.width, size.height);
265:                        w.setVisible(true);
266:                    }
267:                });
268:                // Ensure the window is visible before returning
269:                waitForWindow(w, true);
270:            }
271:
272:            /** Return when the window is ready for input or times out waiting.
273:             * @param w
274:             */
275:            public void waitForWindow(Window w, boolean visible) {
276:                long start = System.currentTimeMillis();
277:                while ((Robot.getEventMode() == Robot.EM_ROBOT && visible && !getWindowTracker()
278:                        .isWindowReady(w))
279:                        || w.isShowing() != visible) {
280:                    long elapsed = System.currentTimeMillis() - start;
281:                    if (elapsed > WINDOW_DELAY)
282:                        throw new RuntimeException(
283:                                "Timed out waiting for Window to "
284:                                        + (visible ? "open" : "close") + " ("
285:                                        + elapsed + "ms)");
286:                    getRobot().sleep();
287:                }
288:            }
289:
290:            /** Synchronous, safe hide of a window.  The window is ensured to be
291:             * hidden ({@link java.awt.event.ComponentEvent#COMPONENT_HIDDEN} or
292:             * equivalent has been posted) when this method returns.  Note that this
293:             * will <em>not</em> trigger a 
294:             * {@link java.awt.event.WindowEvent#WINDOW_CLOSING} event; use
295:             * {@link abbot.tester.WindowTester#actionClose(Component)}
296:             * if a window manager window close operation is required. 
297:             */
298:            public void hideWindow(final Window w) {
299:                EventQueue.invokeLater(new Runnable() {
300:                    public void run() {
301:                        w.setVisible(false);
302:                    }
303:                });
304:                waitForWindow(w, false);
305:                // Not strictly required, but if a test is depending on a window
306:                // event listener's actions on window hide/close, better to wait.
307:                getRobot().waitForIdle();
308:            }
309:
310:            /** Synchronous, safe dispose of a window.  The window is ensured to be
311:             * disposed ({@link java.awt.event.WindowEvent#WINDOW_CLOSED} has been
312:             * posted) when this method returns. 
313:             */
314:            public void disposeWindow(Window w) {
315:                w.dispose();
316:                waitForWindow(w, false);
317:                getRobot().waitForIdle();
318:            }
319:
320:            /** Convenience for <code>getRobot().invokeAndWait(Runnable)</code>. */
321:            public void invokeAndWait(Runnable runnable) {
322:                getRobot().invokeAndWait(runnable);
323:            }
324:
325:            /** Convenience for <code>getRobot().invokeLater(Runnable)</code>. */
326:            public void invokeLater(Runnable runnable) {
327:                getRobot().invokeLater(runnable);
328:            }
329:
330:            /** Install the given popup on the given component.  Takes care of
331:             * installing the appropriate mouse handler to activate the popup.
332:             */
333:            public void installPopup(Component invoker, final JPopupMenu popup) {
334:                invoker.addMouseListener(new MouseAdapter() {
335:                    public void mousePressed(MouseEvent e) {
336:                        mouseReleased(e);
337:                    }
338:
339:                    public void mouseClicked(MouseEvent e) {
340:                        mouseReleased(e);
341:                    }
342:
343:                    public void mouseReleased(MouseEvent e) {
344:                        if (e.isPopupTrigger()) {
345:                            popup.show(e.getComponent(), e.getX(), e.getY());
346:                        }
347:                    }
348:                });
349:            }
350:
351:            /** Safely install and display a popup in the center of the given
352:             * component, returning when it is visible.  Does not install any mouse
353:             * handlers not generate any mouse events. 
354:             */
355:            public void showPopup(final JPopupMenu popup,
356:                    final Component invoker) {
357:                showPopup(popup, invoker, invoker.getWidth() / 2, invoker
358:                        .getHeight() / 2);
359:            }
360:
361:            /** Safely install and display a popup, returning when it is visible.
362:                Does not install any mouse handlers not generate any mouse events.
363:             */
364:            public void showPopup(final JPopupMenu popup,
365:                    final Component invoker, final int x, final int y) {
366:                EventQueue.invokeLater(new Runnable() {
367:                    public void run() {
368:                        popup.show(invoker, x, y);
369:                    }
370:                });
371:                long start = System.currentTimeMillis();
372:                while (!popup.isShowing()) {
373:                    if (System.currentTimeMillis() - start > POPUP_DELAY)
374:                        throw new RuntimeException(
375:                                "Timed out waiting for popup to show");
376:                    robot.sleep();
377:                }
378:                waitForWindow(SwingUtilities.getWindowAncestor(popup), true);
379:            }
380:
381:            /** Display a modal dialog and wait for it to show.  Useful for things
382:             * like
383:             * {@link javax.swing.JFileChooser#showOpenDialog(java.awt.Component)} or
384:             * {@link javax.swing.JOptionPane#showInputDialog(Object)}, or any
385:             * other instance where the dialog contents are not predefined and
386:             * displaying the dialog involves anything more than 
387:             * {@link Window#setVisible(boolean) show()/setVisible(true} 
388:             * (if {@link Window#setVisible(boolean) show()/setVisible(true)} is all 
389:             * that is required, use the {@link #showWindow(Window)} method instead).<p>
390:             * The given {@link Runnable} should contain the code which will show the
391:             * modal {@link Dialog} (and thus block); it will be run on the event
392:             * dispatch thread.<p>
393:             * This method will return when a {@link Dialog} becomes visible which
394:             * contains the given component (which may be any component which will
395:             * appear on the {@link Dialog}), or the standard timeout (10s) is
396:             * reached, at which point a {@link RuntimeException} will be thrown.<p>
397:             * For example,<br>
398:             <pre><code>
399:             final Frame parent = ...;
400:             Dialog d = showModalDialog(new Runnable) {
401:                 public void run() {
402:                     JOptionPane.showInputDialog(parent, "Hit me");
403:                 }
404:             });
405:             </code></pre> 
406:             @see #showWindow(java.awt.Window)
407:             @see #showWindow(java.awt.Window,java.awt.Dimension)
408:             @see #showWindow(java.awt.Window,java.awt.Dimension,boolean)
409:             */
410:            public Dialog showModalDialog(final Runnable showAction)
411:                    throws ComponentSearchException {
412:                return showModalDialog(showAction, new BasicFinder(hierarchy));
413:            }
414:
415:            /** Same as {@link #showModalDialog(Runnable)}, but provides a custom
416:             * {@link ComponentFinder} to find the dialog.
417:             */
418:            public Dialog showModalDialog(final Runnable showAction,
419:                    ComponentFinder finder) throws ComponentSearchException {
420:                final boolean[] modalRun = { false };
421:                final boolean[] invocationFinished = { false };
422:                EventQueue.invokeLater(new Runnable() {
423:                    public void run() {
424:                        modalRun[0] = true;
425:                        try {
426:                            showAction.run();
427:                        } finally {
428:                            // Detect premature Runnable return
429:                            invocationFinished[0] = true;
430:                        }
431:                    }
432:                });
433:                while (!modalRun[0]) {
434:                    try {
435:                        Thread.sleep(10);
436:                    } catch (InterruptedException e) {
437:                    }
438:                }
439:                // Wait for any modal dialog to appear
440:                Matcher matcher = new ClassMatcher(Dialog.class, true) {
441:                    public boolean matches(Component c) {
442:                        return super .matches(c) && ((Dialog) c).isModal()
443:                                && AWT.containsFocus(c);
444:                    }
445:                };
446:                long start = System.currentTimeMillis();
447:                boolean finished = false;
448:                while (true) {
449:                    try {
450:                        return (Dialog) finder.find(matcher);
451:                    } catch (ComponentSearchException e) {
452:                        if (invocationFinished[0]) {
453:                            // ensure we do one more check to see if the dialog is there
454:                            if (finished)
455:                                break;
456:                            finished = true;
457:                        }
458:                        if (System.currentTimeMillis() - start > 10000)
459:                            throw new ComponentSearchException(
460:                                    "Timed out waiting for dialog to be ready");
461:                        robot.sleep();
462:                    }
463:                }
464:                throw new ComponentSearchException(
465:                        "No dialog was displayed (premature return=" + finished
466:                                + ")");
467:            }
468:
469:            /** Returns whether a Component is showing.  The ID may be the component
470:             * name or, in the case of a Frame or Dialog, the title.  Regular
471:             * expressions may be used, but must be delimited by slashes, e.g. /expr/.
472:             * Returns if one or more matches is found.
473:             */
474:            public boolean isShowing(String id) {
475:                return isShowing(id, new BasicFinder(hierarchy));
476:            }
477:
478:            /** Same as {@link #isShowing(String)}, but uses the given 
479:             * ComponentFinder to do the lookup.
480:             */
481:            public boolean isShowing(String id, ComponentFinder finder) {
482:                try {
483:                    finder.find(new WindowMatcher(id, true));
484:                } catch (ComponentNotFoundException e) {
485:                    return false;
486:                } catch (MultipleComponentsFoundException m) {
487:                    // Might not be the one you want, but that's what the docs say
488:                }
489:                return true;
490:            }
491:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.