1 /*
   2  * Copyright (c) 2009, 2016, 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. Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  */
  24 
  25 package test.javaclient.shared;
  26 
  27 import com.sun.glass.ui.Application;
  28 import com.sun.glass.ui.Robot;
  29 import java.io.File;
  30 import java.util.concurrent.Semaphore;
  31 import javafx.application.Platform;
  32 import javafx.scene.Node;
  33 import javafx.scene.SnapshotParameters;
  34 import javafx.scene.image.ImageView;
  35 import org.jemmy.Point;
  36 import org.jemmy.action.GetAction;
  37 import org.jemmy.control.Wrap;
  38 import org.jemmy.env.Environment;
  39 import org.jemmy.fx.Lookups;
  40 import org.jemmy.fx.NodeDock;
  41 import org.jemmy.fx.Root;
  42 import org.jemmy.interfaces.Parent;
  43 import org.jemmy.timing.State;
  44 import org.junit.After;
  45 import org.junit.Assert;
  46 import org.junit.Before;
  47 import org.junit.BeforeClass;
  48 import test.javaclient.shared.screenshots.ScreenshotUtils;
  49 import static test.javaclient.shared.TestUtil.isEmbedded;
  50 import test.javaclient.shared.screenshots.GoldenImageManager;
  51 
  52 /**
  53  * Base class for scenegraph tests. Provides jemmy initialization, scene finding
  54  * and {@link test.scenegraph.app.AbstractApp} based tests support.
  55  *
  56  * @author Sergey Grinev, Andrey Glushchenko
  57  */
  58 public class TestBase extends TestBaseBase {
  59 
  60     private static boolean isTest = false;
  61     protected static Robot robot = null;
  62 
  63     static {
  64         Utils.initializeAwt();
  65         if (Utils.isMacOS()) {
  66             JemmyUtils.runInOtherJVM(true);
  67         }
  68     }
  69 
  70     @BeforeClass
  71     public static void setUpClass() {
  72         TestBaseBase.setUpClass();
  73         isTest = true;
  74     }
  75 
  76     public static boolean isTest() {
  77         return isTest;
  78     }
  79     /*
  80      * I don't know what is it, but many tests use it. Copy from TestBaseOld
  81      *
  82      */
  83     public void setWaitImageDelay(long _delay) {
  84         if(isEmbedded()) {
  85             _delay += 18000;
  86         }
  87         Root.ROOT.getEnvironment().setTimeout(Wrap.WAIT_STATE_TIMEOUT, _delay);
  88     }
  89 
  90     @Before
  91     @Override
  92     public void before() {
  93         super.before();
  94     }
  95     protected void testCommon(String name) {
  96         testCommon(name, null, true, false);
  97     }
  98     public void testCommon(String toplevel_name, String innerlevel_name) {
  99         testCommon(toplevel_name, innerlevel_name, true, false);
 100     }
 101     public void testCommon(String toplevel_name, String innerlevel_name, int pagesNumber) {
 102         testCommon(toplevel_name, innerlevel_name, true, false, pagesNumber);
 103     }
 104     public void testCommon(String toplevel_name, String innerlevel_name, boolean shoots, boolean valuable_rect) {
 105         testExecuter(toplevel_name, innerlevel_name, shoots, valuable_rect, 1);
 106     }
 107     public void testCommon(String toplevel_name, String innerlevel_name, boolean shoots, boolean valuable_rect, int pagesNumber) {
 108         testExecuter(toplevel_name, innerlevel_name, shoots, valuable_rect, pagesNumber);
 109     }
 110     protected void testExecuter(String toplevel_name, String innerlevel_name, boolean shoots, boolean valuable_rect, int pagesNumber) {
 111         testExecuter(toplevel_name, innerlevel_name, shoots, valuable_rect, pagesNumber,true);
 112 
 113     }
 114     /**
 115      * For embedded purpose.
 116      *
 117      * @param pagesNumber define number of control variations to show on the
 118      * page(1 for normal mode, several for embedded mode). pageName is local
 119      * variable to store original page name, it is modified in case of embedded
 120      * mode : PageNameFirst, ... see TestUtil SUFFIXES array
 121      */
 122     protected void testExecuter(final String toplevel_name, final String innerlevel_name, boolean shoots, boolean valuable_rect, int pagesNumber,boolean throwErrors) {
 123         boolean isEmbedded = TestUtil.isEmbedded();
 124         String pageName = toplevel_name;
 125         if (!isEmbedded) {
 126             pagesNumber = 1;
 127         }
 128         for (int i = 0; i < pagesNumber; i++) {
 129             //checking pagesNumber > 1 to use suffixes only in case of embedded mode and multiply page slots
 130             if (isEmbedded && pagesNumber > 1) {
 131                 pageName = toplevel_name;
 132                 pageName += TestUtil.SUFFIXES[i];
 133             }
 134 
 135 
 136             getScene().mouse().move(new Point(0, 0));
 137             final String pageNameForTest = pageName;
 138 
 139             new GetAction() {
 140                 @Override
 141                 public void run(Object... parameters) {
 142 
 143                     if ( null == application ) { // sometimes in applet. reason: unknown
 144                      application = AbstractApp2.getLastInstance();
 145                     }
 146 
 147                     final TestNode tn = getApplication().openPage(pageNameForTest, innerlevel_name);
 148                     Assert.assertNotNull(tn);
 149                     Assert.assertNotNull("Test node named: '"
 150                                     + pageNameForTest + ((null == innerlevel_name) ? "" : (" - " + innerlevel_name))
 151                                     + "' wasnt found in :" + application.toString(),tn);
 152                 }
 153             }.dispatch(Environment.getEnvironment());
 154 
 155             try {
 156                 Thread.sleep(600); // ugly workaround to be removed ASAP
 157             } catch (InterruptedException ex) {
 158                 ex.printStackTrace();
 159             }
 160             verifyFailures();
 161 
 162             if (shoots) {
 163                 try {
 164                     Thread.sleep(AppLauncher.getInstance().getTestDelay());
 165                 } catch (InterruptedException ex) {
 166                     ex.printStackTrace();
 167                 }
 168                 //verify screenshot
 169                 String normalizedName = Utils.normalizeName(pageName + (innerlevel_name != null ? innerlevel_name : ""));
 170                 ScreenshotUtils.checkPageContentScreenshot(new StringBuilder(getName()).append("-").append(normalizedName).toString(), valuable_rect);
 171                 if (throwErrors) {
 172                     ScreenshotUtils.throwScreenshotErrors();
 173                 }
 174             }
 175         }
 176     }
 177 
 178     private void doRenderToImageAndWait(final Wrap<? extends Node> noda,
 179             final SnapshotParameters _sp) {
 180         // 2. do "RenderToImage", show rendered image in ImageView, replace scene root
 181         // with tmp Group with ImageView in it.
 182         new GetAction() {
 183             @Override
 184             public void run(Object... parameters) {
 185                 ((BasicButtonChooserApp) application).doRenderToImage(getScene().getControl(),
 186                         (null == noda) ? null : noda.getControl(), _sp);
 187             }
 188         }.dispatch(Environment.getEnvironment());
 189 
 190         // wait rendered image ready
 191         getScene().waitState(new State() {
 192             public Object reached() {
 193                 if ((new GetAction() {
 194                     @Override
 195                     public void run(Object... parameters) {
 196                         if (((BasicButtonChooserApp) application).isImageReady()) {
 197                             setResult(Boolean.TRUE);
 198                         }
 199                     }
 200                 }.dispatch(Environment.getEnvironment())) == Boolean.TRUE) {
 201                     return Boolean.TRUE;
 202                 }
 203                 return null;
 204             }
 205         });
 206     }
 207 
 208     public void testCommonsAdditional(String slotName, String additionalActionButtonName) {
 209         openPage(slotName);
 210         clickTextButton(additionalActionButtonName);
 211         verifyGetters();
 212 
 213         //verify screenshot
 214         ScreenshotUtils.checkPageContentScreenshot(new StringBuilder(getName()).append("-").append(slotName).append("-").append("additional").toString());
 215 
 216     }
 217 
 218     public void testAdditionalAction(String toplevel_name, String innerlevel_name) {
 219         testAdditionalAction(toplevel_name, innerlevel_name, true);
 220     }
 221 
 222     public void testAdditionalAction(String toplevel_name, String innerlevel_name, boolean shoots) {
 223         testAdditionalAction(toplevel_name, innerlevel_name, shoots, true);
 224     }
 225 
 226     public void testAdditionalAction(final String toplevel_name, final String innerlevel_name, boolean shoots, boolean throwError) {
 227         getScene().mouse().move(new Point(0, 0));
 228         try {
 229             Thread.sleep(100); // ugly workaround to be removed ASAP
 230         } catch (InterruptedException ex) {
 231         }
 232         if ( null == application ) { // sometimes in applet. reason: unknown
 233             application = AbstractApp2.getLastInstance();
 234         }
 235 
 236         Assert.assertNotNull(application);  //sometimes
 237         new GetAction() {
 238             @Override
 239             public void run(Object... parameters) {
 240                 TestNode tn =
 241                         application.openPage(toplevel_name, innerlevel_name);
 242                         Assert.assertNotNull(tn);
 243             }
 244         }.dispatch(Environment.getEnvironment());
 245 
 246         try {
 247             Thread.sleep(100); // ugly workaround to be removed ASAP
 248         } catch (InterruptedException ex) {
 249         }
 250         new GetAction() {
 251             @Override
 252             public void run(Object... parameters) {
 253                 application.doAdditionalAction(toplevel_name, innerlevel_name);
 254             }
 255         }.dispatch(Environment.getEnvironment());
 256 
 257         try {
 258             Thread.sleep(400); // ugly workaround to be removed ASAP
 259         } catch (InterruptedException ex) {
 260         }
 261         verifyFailures();
 262 
 263         if (shoots) {
 264             //verify screenshot
 265             String testName = new StringBuilder(getName()).append("-").append(toplevel_name).append(innerlevel_name).append("-").append("additional").toString();
 266             String pathToGoldenScreenshot = GoldenImageManager.getScreenshotPath(testName);
 267             if (!(new File(pathToGoldenScreenshot)).exists()) {
 268                 testName = new StringBuilder(getName()).append("-").append(toplevel_name).append(innerlevel_name).toString();
 269             }
 270             ScreenshotUtils.checkPageContentScreenshot(testName);
 271             if (throwError) {
 272                 ScreenshotUtils.throwScreenshotErrors();
 273             }
 274         }
 275 
 276     }
 277 
 278     public void testRenderSceneToImage(String toplevel_name, String innerlevel_name) { //SCENE
 279         testRenderSomethingToImage(toplevel_name, innerlevel_name, "scene-",
 280                 null);
 281 
 282     }
 283 
 284     public void testRenderSomethingToImage(String toplevel_name, String innerlevel_name,
 285             String prefixForFilename, final Wrap<? extends Node> noda) {
 286 
 287         String filename = prefixForFilename + getNameForScreenShot(toplevel_name, innerlevel_name);
 288         org.jemmy.image.Image imageJemmy = (null == noda) ? getScene().getScreenImage() : noda.getScreenImage();
 289 
 290         String resName = GoldenImageManager.getScreenshotPath(filename);
 291         String res2Name = GoldenImageManager.getScreenshotPath(filename + "-2");
 292 
 293         imageJemmy.save(resName);
 294 
 295         doRenderToImageAndWait(noda, null);
 296 
 297         // TAKE A SHOT USING JEMMY, save it (scene with ImageView with rendered image in it)
 298         //org.jemmy.image.Image sceneImageJemmy2 = scene.getScreenImage();
 299         //sceneImageJemmy2.save(ImagesManager.getInstance().getScreenshotPath(filename + "2"));
 300 
 301         String diffName = GoldenImageManager.getScreenshotPath(filename + "-diff");
 302         boolean scenesEqual = true;
 303         try {
 304             if (null == noda) {
 305                 getScene().waitImage(getScene().getEnvironment().getImageLoader().load(resName),
 306                         res2Name, diffName);
 307             } else {
 308                 Wrap<? extends Node> imViewWrap =
 309                         //(new NodeDock(getScene().as(Parent.class, Node.class), "ViewOfNodeSnapshot")).wrap();
 310                         (new NodeDock((Parent<Node>)getScene().as(Parent.class, Node.class), "ViewOfNodeSnapshot")).wrap();
 311                 //Lookups.byID(scene, "ViewOfNodeSnapshot", ImageView.class);
 312 
 313                 imViewWrap.waitImage(getScene().getEnvironment().getImageLoader().load(resName),
 314                         res2Name, diffName);
 315             }
 316         } catch (org.jemmy.TimeoutExpiredException ex) {
 317             scenesEqual = false;
 318         } finally {
 319             restoreSceneRoot();
 320         }
 321 
 322         if (scenesEqual) {
 323             System.out.print("delete scene- and node- images.... ");
 324             new File(resName).delete();
 325             new File(res2Name).delete();
 326             System.out.println(" Completed.");
 327         } else {
 328             System.out.print("scene/node render to image failed.");
 329             throw new org.jemmy.TimeoutExpiredException("waitImage failed for file:" + resName);
 330         }
 331     }
 332     public void testNodeSnapshotWithParameters (String toplevel_name, String innerlevel_name,
 333             final SnapshotParameters _sp, final String param_name) {
 334 
 335         final Wrap<? extends Node> noda = ScreenshotUtils.getPageContent();
 336         doRenderToImageAndWait(noda, _sp);
 337 
 338         org.jemmy.TimeoutExpiredException saved_ex = null;
 339         try {
 340 
 341                 Wrap<? extends Node> imViewWrap =
 342                         Lookups.byID(getScene(), "ViewOfNodeSnapshot", ImageView.class);
 343 
 344                 ScreenshotUtils.checkScreenshot(new StringBuilder(getName()).append("-")
 345                         .append(param_name).toString(), imViewWrap);
 346 
 347         } catch (org.jemmy.TimeoutExpiredException ex) {
 348             saved_ex = ex;
 349         } finally {
 350             restoreSceneRoot();
 351         }
 352         if ( null != saved_ex) {
 353             throw saved_ex;
 354         }
 355     }
 356 
 357     /**
 358      * Utility method to slow down test if specific keys is set (false by
 359      * default)
 360      */
 361     @After
 362     public void after() {
 363         TestUtil.slow(1000);
 364     }
 365 
 366     protected void dnd(final Wrap from, final Wrap to) {
 367         Point fromPoint = from.getClickPoint();
 368         Point toPoint = to.getClickPoint();
 369         if (from.getControl() == to.getControl()) {
 370             //If "from" control is the same as "to" control, drag is performed within a control
 371             //from top-left corner to bottom-right corner.
 372             double width = from.getScreenBounds().width / 3;
 373             double height = from.getScreenBounds().height / 3;
 374             fromPoint.move((int) (fromPoint.x - width), (int) (fromPoint.y - height));
 375             toPoint.move((int) (toPoint.x + width), (int) (toPoint.y + height));
 376         }
 377         dnd(from, fromPoint, to, toPoint);
 378     }
 379 
 380     protected void dnd(Wrap from, Point fromPoint, Wrap to, Point toPoint) {
 381         try {
 382             if (!Utils.isWindows()) {
 383                 System.err.println("Use jemmy robot");
 384                 from.drag().dnd(fromPoint, to, toPoint);
 385             } else {
 386                 System.err.println("Use Glass robot");
 387                 dndRobot(from, fromPoint, to, toPoint);
 388             }
 389             Thread.sleep(1000);
 390         } catch (InterruptedException ex) {
 391             System.err.println("Error while DnD: " + ex);
 392         }
 393     }
 394 
 395     private void dndRobot(Wrap from, Point fromPoint, Wrap to, Point toPoint) throws InterruptedException {
 396         Point absFromPoint = new Point(fromPoint);
 397         Point absToPoint = new Point(toPoint);
 398         absFromPoint.translate((int) from.getScreenBounds().getX(), (int) from.getScreenBounds().getY());
 399         absToPoint.translate((int) to.getScreenBounds().getX(), (int) to.getScreenBounds().getY());
 400         Semaphore s = new Semaphore(0);
 401         Platform.runLater(() -> {
 402             if (robot == null) {
 403                 robot = Application.GetApplication().createRobot();
 404             }
 405             robot.mouseMove(absFromPoint.x, absFromPoint.y);
 406             robot.mousePress(Robot.MOUSE_LEFT_BTN);
 407             final int STEPS = 50;
 408             int dx = absToPoint.x - absFromPoint.x;
 409             int dy = absToPoint.y - absFromPoint.y;
 410             for (int i = 0; i <= STEPS; i++) {
 411                 robot.mouseMove(absFromPoint.x + dx * i / STEPS, absFromPoint.y + dy * i / STEPS);
 412                 try {
 413                     Thread.sleep(20);
 414                 } catch (InterruptedException ex) {
 415                     System.err.println("Error while dragging: " + ex);
 416                     ex.printStackTrace();
 417                 }
 418             }
 419             robot.mouseRelease(Robot.MOUSE_LEFT_BTN);
 420             s.release();
 421         });
 422         s.acquire();
 423     }
 424 }