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 //Lookups.byID(scene, "ViewOfNodeSnapshot", ImageView.class); 311 312 imViewWrap.waitImage(getScene().getEnvironment().getImageLoader().load(resName), 313 res2Name, diffName); 314 } 315 } catch (org.jemmy.TimeoutExpiredException ex) { 316 scenesEqual = false; 317 } finally { 318 restoreSceneRoot(); 319 } 320 321 if (scenesEqual) { 322 System.out.print("delete scene- and node- images.... "); 323 new File(resName).delete(); 324 new File(res2Name).delete(); 325 System.out.println(" Completed."); 326 } else { 327 System.out.print("scene/node render to image failed."); 328 throw new org.jemmy.TimeoutExpiredException("waitImage failed for file:" + resName); 329 } 330 } 331 public void testNodeSnapshotWithParameters (String toplevel_name, String innerlevel_name, 332 final SnapshotParameters _sp, final String param_name) { 333 334 final Wrap<? extends Node> noda = ScreenshotUtils.getPageContent(); 335 doRenderToImageAndWait(noda, _sp); 336 337 org.jemmy.TimeoutExpiredException saved_ex = null; 338 try { 339 340 Wrap<? extends Node> imViewWrap = 341 Lookups.byID(getScene(), "ViewOfNodeSnapshot", ImageView.class); 342 343 ScreenshotUtils.checkScreenshot(new StringBuilder(getName()).append("-") 344 .append(param_name).toString(), imViewWrap); 345 346 } catch (org.jemmy.TimeoutExpiredException ex) { 347 saved_ex = ex; 348 } finally { 349 restoreSceneRoot(); 350 } 351 if ( null != saved_ex) { 352 throw saved_ex; 353 } 354 } 355 356 /** 357 * Utility method to slow down test if specific keys is set (false by 358 * default) 359 */ 360 @After 361 public void after() { 362 TestUtil.slow(1000); 363 } 364 365 protected void dnd(final Wrap from, final Wrap to) { 366 Point fromPoint = from.getClickPoint(); 367 Point toPoint = to.getClickPoint(); 368 if (from.getControl() == to.getControl()) { 369 //If "from" control is the same as "to" control, drag is performed within a control 370 //from top-left corner to bottom-right corner. 371 double width = from.getScreenBounds().width / 3; 372 double height = from.getScreenBounds().height / 3; 373 fromPoint.move((int) (fromPoint.x - width), (int) (fromPoint.y - height)); 374 toPoint.move((int) (toPoint.x + width), (int) (toPoint.y + height)); 375 } 376 dnd(from, fromPoint, to, toPoint); 377 } 378 379 protected void dnd(Wrap from, Point fromPoint, Wrap to, Point toPoint) { 380 try { 381 if (!Utils.isWindows()) { 382 System.err.println("Use jemmy robot"); 383 from.drag().dnd(fromPoint, to, toPoint); 384 } else { 385 System.err.println("Use Glass robot"); 386 dndRobot(from, fromPoint, to, toPoint); 387 } 388 Thread.sleep(1000); 389 } catch (InterruptedException ex) { 390 System.err.println("Error while DnD: " + ex); 391 } 392 } 393 394 private void dndRobot(Wrap from, Point fromPoint, Wrap to, Point toPoint) throws InterruptedException { 395 Point absFromPoint = new Point(fromPoint); 396 Point absToPoint = new Point(toPoint); 397 absFromPoint.translate((int) from.getScreenBounds().getX(), (int) from.getScreenBounds().getY()); 398 absToPoint.translate((int) to.getScreenBounds().getX(), (int) to.getScreenBounds().getY()); 399 Semaphore s = new Semaphore(0); 400 Platform.runLater(() -> { 401 if (robot == null) { 402 robot = Application.GetApplication().createRobot(); 403 } 404 robot.mouseMove(absFromPoint.x, absFromPoint.y); 405 robot.mousePress(Robot.MOUSE_LEFT_BTN); 406 final int STEPS = 50; 407 int dx = absToPoint.x - absFromPoint.x; 408 int dy = absToPoint.y - absFromPoint.y; 409 for (int i = 0; i <= STEPS; i++) { 410 robot.mouseMove(absFromPoint.x + dx * i / STEPS, absFromPoint.y + dy * i / STEPS); 411 try { 412 Thread.sleep(20); 413 } catch (InterruptedException ex) { 414 System.err.println("Error while dragging: " + ex); 415 ex.printStackTrace(); 416 } 417 } 418 robot.mouseRelease(Robot.MOUSE_LEFT_BTN); 419 s.release(); 420 }); 421 s.acquire(); 422 } 423 }