1 /*
   2  * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.jemmy.input;
  24 
  25 
  26 import java.awt.AWTException;
  27 import java.awt.BorderLayout;
  28 import java.awt.Button;
  29 import java.awt.EventQueue;
  30 import java.awt.Frame;
  31 import java.awt.Robot;
  32 import java.awt.event.InputEvent;
  33 import java.awt.event.KeyAdapter;
  34 import java.awt.event.KeyEvent;
  35 import java.awt.event.MouseAdapter;
  36 import java.awt.event.MouseEvent;
  37 import java.io.File;
  38 import java.lang.reflect.InvocationTargetException;
  39 import org.jemmy.Point;
  40 import org.jemmy.control.Wrap;
  41 import org.jemmy.env.Environment;
  42 import org.jemmy.env.Timeout;
  43 import org.jemmy.image.AWTImage;
  44 import org.jemmy.interfaces.Keyboard;
  45 import org.jemmy.interfaces.Keyboard.KeyboardButton;
  46 import org.jemmy.interfaces.Keyboard.KeyboardButtons;
  47 import org.jemmy.interfaces.Keyboard.KeyboardModifiers;
  48 import org.jemmy.interfaces.Modifier;
  49 import org.jemmy.interfaces.Mouse;
  50 import org.jemmy.interfaces.Mouse.MouseButton;
  51 import org.jemmy.interfaces.Mouse.MouseButtons;
  52 import org.jemmy.timing.State;
  53 import org.jemmy.timing.Waiter;
  54 import org.testng.annotations.AfterClass;
  55 import org.testng.annotations.AfterMethod;
  56 import org.testng.annotations.BeforeClass;
  57 import org.testng.annotations.BeforeMethod;
  58 import org.testng.annotations.Test;
  59 
  60 import static org.testng.Assert.assertFalse;
  61 import static org.testng.Assert.assertTrue;
  62 
  63 
  64 /**
  65  *
  66  * @author Alexander Kouznetsov <mrkam@mail.ru>
  67  */
  68 public class RobotDriverTest {
  69 
  70     final static Timeout TIMEOUT = new Timeout("Wait for state to be reached", 10000);
  71     final static Timeout DELTA_TIMEOUT = new Timeout("Delta timeout of wait for state to be reached", 1000);
  72 
  73     public RobotDriverTest() {
  74     }
  75 
  76     @BeforeClass
  77     public static void setUpClass() throws Exception {
  78         File workdir = new File(System.getProperty("user.dir") + File.separator +
  79                 "build" + File.separator +
  80                 "test" + File.separator +
  81                 "results");
  82         workdir.mkdirs();
  83         AWTImage.setImageRoot(workdir);
  84     }
  85 
  86     @AfterClass
  87     public static void tearDownClass() throws Exception {
  88         RobotDriver.exit();
  89     }
  90 
  91     Frame frm;
  92     Button btn;
  93     Wrap<Object> area;
  94     private volatile boolean mousePressed;
  95     private volatile boolean mouseReleased;
  96     private volatile boolean mouseMoved;
  97     private volatile boolean mouseClicked;
  98     private volatile boolean mouseDragged;
  99     private volatile boolean keyPressed;
 100     private volatile boolean keyReleased;
 101     RobotDriver instance;
 102     Robot rb;
 103 
 104     @BeforeMethod
 105     public void setUp() throws InterruptedException, AWTException, InvocationTargetException {
 106         EventQueue.invokeAndWait(new Runnable() {
 107 
 108             public void run() {
 109                 frm = new Frame("some frame");
 110                 frm.setSize(100, 100);
 111                 frm.setLocation(100, 100);
 112                 btn = new Button("some button");
 113                 MouseAdapter m = new MouseAdapter() {
 114 
 115                     @Override
 116                     public void mousePressed(MouseEvent e) {
 117                         System.out.println("mousePressed event triggered: " + e);
 118                         System.out.flush();
 119                         if ((e.getButton() & MouseEvent.BUTTON1) != 0 && e.isShiftDown()) {
 120                             mousePressed = true;
 121                         }
 122                     }
 123 
 124                     @Override
 125                     public void mouseReleased(MouseEvent e) {
 126                         System.out.println("mouseReleased event triggered: " + e);
 127                         System.out.flush();
 128                         if ((e.getButton() & MouseEvent.BUTTON2) != 0 && e.isControlDown()) {
 129                             mouseReleased = true;
 130                         }
 131                     }
 132 
 133                     @Override
 134                     public void mouseMoved(MouseEvent e) {
 135                         System.out.println("mouseMoved event triggered: " + e);
 136                         System.out.flush();
 137                         mouseMoved = true;
 138                     }
 139 
 140                     @Override
 141                     public void mouseClicked(MouseEvent e) {
 142                         System.out.println("mouseClicked event triggered: " + e);
 143                         System.out.flush();
 144                         if ((e.getButton() & MouseEvent.BUTTON3) != 0 && e.isAltDown()) {
 145                             mouseClicked = true;
 146                         }
 147                     }
 148 
 149                     @Override
 150                     public void mouseDragged(MouseEvent e) {
 151                         System.out.println("mouseDragged event triggered: " + e);
 152                         System.out.flush();
 153                         if ((e.getModifiers() & MouseEvent.BUTTON2_MASK) != 0) {
 154                             mouseDragged = true;
 155                         }
 156                     }
 157 
 158                 };
 159                 btn.addMouseListener(m);
 160                 btn.addMouseMotionListener(m);
 161                 btn.addKeyListener(new KeyAdapter() {
 162 
 163                     @Override
 164                     public void keyPressed(KeyEvent e) {
 165                         System.out.println("keyPressed event triggered: " + e);
 166                         System.out.flush();
 167                         if (e.getKeyCode() == KeyEvent.VK_A && e.isShiftDown()) {
 168                             keyPressed = true;
 169                         }
 170                     }
 171 
 172                     @Override
 173                     public void keyReleased(KeyEvent e) {
 174                         System.out.println("keyReleased event triggered: " + e);
 175                         System.out.flush();
 176                         if (e.getKeyCode() == KeyEvent.VK_B) {
 177                             keyReleased = true;
 178                         }
 179                     }
 180 
 181                 });
 182                 frm.add(btn, BorderLayout.SOUTH);
 183                 frm.doLayout();
 184                 instance = new RobotDriver(Environment.getEnvironment());
 185                 frm.setVisible(true);
 186                 btn.requestFocusInWindow();
 187             }
 188         });
 189 
 190         rb = new Robot();
 191         rb.waitForIdle();
 192 
 193         RobotExecutor.get().setRunInOtherJVM(true);
 194     }
 195 
 196     @AfterMethod
 197     public void tearDown() throws InterruptedException, InvocationTargetException {
 198         EventQueue.invokeAndWait(new Runnable() {
 199 
 200             public void run() {
 201                 frm.setVisible(false);
 202             }
 203         });
 204     }
 205 
 206 //    /**
 207 //     * Test of createScreenCapture method, of class RobotDriver.
 208 //     */
 209 //    @Test
 210 //    public void testCreateScreenCaptureLocally() throws AWTException, InterruptedException {
 211 //        System.out.println("testCreateScreenCaptureLocally");
 212 //        Thread.sleep(3000);
 213 //        Rectangle screenRect = new Rectangle(100, 100, 100, 100);
 214 //        RobotExecutor.get().setRunInOtherJVM(false);
 215 //        Image expResult = new AWTImage(new Robot().createScreenCapture(new java.awt.Rectangle(100, 100, 100, 100)));
 216 //        Image result = RobotDriver.createScreenCapture(screenRect);
 217 //        Image diff = expResult.compareTo(result);
 218 //        if (diff != null) {
 219 //            diff.save("testCreateScreenCaptureLocally.png");
 220 //            fail();
 221 //        }
 222 //    }
 223 //
 224 //    /**
 225 //     * Test of createScreenCapture method, of class RobotDriver.
 226 //     */
 227 //    @Test
 228 //    public void testCreateScreenCaptureRemotely() throws AWTException, InterruptedException {
 229 //        System.out.println("testCreateScreenCaptureRemotely");
 230 //        Thread.sleep(3000);
 231 //        Rectangle screenRect = new Rectangle(100, 100, 100, 100);
 232 //        RobotExecutor.get().setRunInOtherJVM(true);
 233 //        Image expResult = new AWTImage(new Robot().createScreenCapture(new java.awt.Rectangle(100, 100, 100, 100)));
 234 //        Image result = RobotDriver.createScreenCapture(screenRect);
 235 //        RobotDriver.createScreenCapture(screenRect);
 236 //        Image diff = expResult.compareTo(result);
 237 //        if (diff != null) {
 238 //            diff.save("testCreateScreenCaptureRemotely.png");
 239 //            fail();
 240 //        }
 241 //    }
 242 //
 243 //    /**
 244 //     * Test of createScreenCapture method, of class RobotDriver.
 245 //     */
 246 //    @Test
 247 //    public void testCreateScreenCaptureRemotely2() throws AWTException, InterruptedException {
 248 //        System.out.println("testCreateScreenCaptureRemotely2");
 249 //        Thread.sleep(3000);
 250 //        Rectangle screenRect = new Rectangle(100, 100, 100, 100);
 251 //        RobotExecutor.get().setRunInOtherJVM(true);
 252 //        Image expResult = new AWTImage(new Robot().createScreenCapture(new java.awt.Rectangle(100, 100, 100, 100)));
 253 //        Image result = RobotDriver.createScreenCapture(screenRect);
 254 //        Image diff = expResult.compareTo(result);
 255 //        if (diff != null) {
 256 //            diff.save("testCreateScreenCaptureRemotely2.png");
 257 //            fail();
 258 //        }
 259 //    }
 260 
 261     /**
 262      * Test of pressMouse method, of class RobotDriver.
 263      */
 264     @Test
 265     public void testPressMouse() throws InterruptedException {
 266         System.out.println("pressMouse");
 267         Thread.sleep(3000);
 268 //        new Thread() {
 269 //
 270 //            @Override
 271 //            public void run() {
 272                 MouseButton mouseButton = MouseButtons.BUTTON1;
 273                 Modifier modifiers[] = new Modifier[] {KeyboardModifiers.SHIFT_DOWN_MASK};
 274                 mousePressed = false;
 275                 java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 276                 System.out.println("Pressing mouse");
 277                 instance.moveMouse(new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2));
 278                 instance.pressMouse(mouseButton, modifiers);
 279                 instance.releaseMouse(mouseButton, modifiers);
 280 
 281                 rb.waitForIdle();
 282                 new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 283 
 284                     public Boolean reached() {
 285                         return mousePressed ? true: null;
 286                     }
 287 
 288                 });
 289 
 290 //            }
 291 //
 292 //        }.start();
 293     }
 294 
 295     /**
 296      * Test of releaseMouse method, of class RobotDriver.
 297      */
 298     @Test
 299     public void testReleaseMouse() throws InterruptedException {
 300         System.out.println("releaseMouse");
 301         Thread.sleep(3000);
 302         MouseButton mouseButton = MouseButtons.BUTTON2;
 303         Modifier modifiers[] = new Modifier[] {KeyboardModifiers.CTRL_DOWN_MASK};
 304         mouseReleased = false;
 305         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 306         instance.moveMouse(new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2));
 307         System.out.println("Pressing mouse");
 308         instance.pressMouse(mouseButton, modifiers);
 309         System.out.println("Releasing mouse");
 310         instance.releaseMouse(mouseButton, modifiers);
 311 
 312         rb.waitForIdle();
 313         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 314 
 315             public Boolean reached() {
 316                 return mouseReleased ? true: null;
 317             }
 318 
 319         });
 320         assertTrue(mouseReleased);
 321     }
 322 
 323     /**
 324      * Test of moveMouse method, of class RobotDriver.
 325      */
 326     @Test
 327     public void testMoveMouse() throws InterruptedException {
 328         System.out.println("moveMouse");
 329         Thread.sleep(3000);
 330         mouseMoved = false;
 331         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 332         System.out.println("Moving mouse");
 333         Point startPoint = new Point(locationOnScreen.x, locationOnScreen.y);
 334         Point endPoint = new Point(locationOnScreen.x + btn.getWidth(), locationOnScreen.y + btn.getHeight());
 335         double steps = 5; //Math.max(btn.getWidth(), btn.getHeight());
 336         double dx = (endPoint.x - startPoint.x) / steps;
 337         double dy = (endPoint.y - startPoint.y) / steps;
 338         for(int i = 0; i < steps; i++) {
 339             Point point = new Point(startPoint.x + dx * i, startPoint.y + dy * i);
 340             instance.moveMouse(point);
 341             Thread.sleep(100);
 342         }
 343 
 344         rb.waitForIdle();
 345         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 346 
 347             public Boolean reached() {
 348                 return mouseMoved ? true: null;
 349             }
 350 
 351         });
 352         assertTrue(mouseMoved);
 353     }
 354 
 355     /**
 356      * Test of moveMouse method with smoothness set Integer.MAX_VALUE
 357      * of class RobotDriver.
 358      */
 359     @Test
 360     public void testMoveNonSmoothMouse() throws InterruptedException {
 361         System.out.println("testMoveNonSmoothMouse");
 362         Thread.sleep(3000);
 363         mouseMoved = false;
 364         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 365         System.out.println("Moving mouse");
 366         Point startPoint = new Point(locationOnScreen.x - 10, locationOnScreen.y - 10);
 367         Point endPoint = new Point(locationOnScreen.x + btn.getWidth() + 10, locationOnScreen.y + btn.getHeight() + 10);
 368         instance.moveMouse(startPoint);
 369         Thread.sleep(100);
 370         instance.moveMouse(endPoint);
 371         Thread.sleep(2000);
 372 
 373         rb.waitForIdle();
 374         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 375 
 376             public Boolean reached() {
 377                 return !mouseMoved ? true : null;
 378             }
 379 
 380         });
 381         assertFalse(mouseMoved);
 382     }
 383 
 384     /**
 385      * Test of clickMouse method, of class RobotDriver.
 386      */
 387     @Test
 388     public void testClickMouse() throws InterruptedException {
 389         System.out.println("clickMouse");
 390         Thread.sleep(3000);
 391         mouseClicked = false;
 392         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 393         Point point = new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2);
 394         int clickCount = 1;
 395         MouseButton mouseButton = MouseButtons.BUTTON3;
 396         Modifier modifiers[] = new Modifier[] {KeyboardModifiers.ALT_DOWN_MASK};
 397         Timeout mouseClick = new Timeout("mouseClick", 100);
 398         System.out.println("Clicking mouse");
 399         instance.clickMouse(point, clickCount, mouseButton, mouseClick, modifiers);
 400 
 401         rb.waitForIdle();
 402         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 403 
 404             public Boolean reached() {
 405                 return mouseClicked ? true: null;
 406             }
 407 
 408         });
 409         assertTrue(mouseClicked);
 410     }
 411 
 412     /**
 413      * Test of dragNDrop method, of class RobotDriver.
 414      */
 415     @Test
 416     public void testDragNDrop() throws InterruptedException {
 417         System.out.println("dragNDrop");
 418         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 419         Point startPoint = new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2);
 420         Point endPoint = new Point(frm.getLocationOnScreen().x + frm.getWidth() / 2, frm.getLocationOnScreen().y + frm.getHeight() / 2);
 421         MouseButton mouseButton = MouseButtons.BUTTON2;
 422         Modifier modifiers[] = new Modifier[] {};
 423         Timeout before = new Timeout("before", 500);
 424         Timeout after = new Timeout("after", 500);
 425         mouseDragged = false;
 426         instance.dragNDrop(startPoint, endPoint, mouseButton, modifiers, before, after);
 427 
 428         rb.waitForIdle();
 429         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 430 
 431             public Boolean reached() {
 432                 return mouseDragged ? true: null;
 433             }
 434 
 435         });
 436         assertTrue(mouseDragged);
 437     }
 438 
 439     /**
 440      * Test of pressKey method, of class RobotDriver.
 441      */
 442     @Test
 443     public void testPressKey() throws InterruptedException {
 444         System.out.println("pressKey");
 445         KeyboardButton kbdButton = KeyboardButtons.A;
 446         Modifier modifiers[] = new Modifier[] {KeyboardModifiers.SHIFT_DOWN_MASK};
 447         keyPressed = false;
 448         instance.pressKey(kbdButton, modifiers);
 449         instance.releaseKey(kbdButton, modifiers);
 450 
 451         rb.waitForIdle();
 452         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 453 
 454             public Boolean reached() {
 455                 return keyPressed ? true: null;
 456             }
 457 
 458         });
 459         assertTrue(keyPressed);
 460     }
 461 
 462     /**
 463      * Test of releaseKey method, of class RobotDriver.
 464      */
 465     @Test
 466     public void testReleaseKey() throws InterruptedException {
 467         System.out.println("releaseKey");
 468         KeyboardButton kbdButton = KeyboardButtons.B;
 469         Modifier modifiers[] = new Modifier[] {};
 470         keyReleased = false;
 471         instance.pressKey(kbdButton, modifiers);
 472         instance.releaseKey(kbdButton, modifiers);
 473 
 474         rb.waitForIdle();
 475         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 476 
 477             public Boolean reached() {
 478                 return keyReleased ? true: null;
 479             }
 480 
 481         });
 482         assertTrue(keyReleased);
 483     }
 484 }