--- /dev/null 2018-05-21 19:06:16.611537000 +0530 +++ new/tests/system/src/test/java/test/robot/javafx/scene/TabContextMenuCloseButtonTest.java 2018-05-21 22:10:03.939737161 +0530 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package test.robot.javafx.scene; + +import com.sun.glass.ui.Robot; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.scene.Scene; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import javafx.stage.WindowEvent; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.fail; + +public class TabContextMenuCloseButtonTest { + + static CountDownLatch startupLatch = new CountDownLatch(1); + static CountDownLatch cmlatch; + static Robot robot; + static TabPane tabPane; + static volatile Stage stage; + static volatile Scene scene; + static ContextMenu cMenu; + static boolean cmShown = false; + static final int SCENE_WIDTH = 250; + static final int SCENE_HEIGHT = SCENE_WIDTH; + final int DX = 17; + final int DY = DX; + + // Test close button with three mouse buttons. + // Pressing left & middle button closes the tab. + // Pressing right button does not close the tab. + @Test + public void testCloseButton() { + int mouseButtons[] = { Robot.MOUSE_MIDDLE_BTN, Robot.MOUSE_RIGHT_BTN, Robot.MOUSE_LEFT_BTN }; + int expectedTabCount[] = {2, 2, 1}; + try { + Thread.sleep(1000); // Wait for tabPane to layout + } catch (Exception ex) { + System.out.println("Thread was interrupted." + ex); + } + for (int i = 0; i < mouseButtons.length; ++i) { + final int ic = i; + CountDownLatch pressLatch = new CountDownLatch(1); + Platform.runLater(() -> { + if (cMenu.isShowing()) { + cMenu.hide(); + } + robot.mouseMove((int) (scene.getWindow().getX() + scene.getX() + DX), + (int) (scene.getWindow().getY() + scene.getY() + DY)); + robot.mousePress(mouseButtons[ic]); + robot.mouseRelease(mouseButtons[ic]); + pressLatch.countDown(); + }); + waitForLatch(pressLatch, 5, "Timeout waiting for Robot.Button." + mouseButtons[i]); + try { + Thread.sleep(500); // Wait for tabPane to layout + } catch (Exception ex) { + System.out.println("Thread was interrupted." + ex); + } + Assert.assertEquals(expectedTabCount[i], tabPane.getTabs().size()); + } + } + + // Test that pressing right mouse button shows context menu. + @Test + public void testContextMenu() { + try { + Thread.sleep(1000); // Wait for tabPane to layout + } catch (Exception ex) { + System.out.println("Thread was interrupted." + ex); + } + cmShown = false; + CountDownLatch pressLatch = new CountDownLatch(1); + cmlatch = new CountDownLatch(1); + cMenu.setOnShown(event -> { + cmShown = true; + cmlatch.countDown(); + }); + Platform.runLater(() -> { + if (cMenu.isShowing()) { + cMenu.hide(); + } + robot.mouseMove((int)(scene.getWindow().getX() + scene.getX() + DX), + (int)(scene.getWindow().getY() + scene.getY() + DY)); + robot.mousePress(Robot.MOUSE_RIGHT_BTN); + robot.mouseRelease(Robot.MOUSE_RIGHT_BTN); + pressLatch.countDown(); + }); + waitForLatch(pressLatch, 5, "Timeout waiting for Robot.MOUSE_RIGHT_BTN."); + waitForLatch(cmlatch, 5, "Timeout waiting for ContextMenu to be shown."); + Assert.assertTrue("Tab's ContextMenu not shown.", cmShown); + } + + public static void setupUI() { + CountDownLatch latch = new CountDownLatch(1); + Platform.runLater(() -> { + cMenu = new ContextMenu(new MenuItem("hello"), new MenuItem("goodbye")); + + for (int i = 0; i < 3; ++i) { + Tab tab = new Tab(""); + tab.setContextMenu(cMenu); + tabPane.getTabs().add(tab); + } + latch.countDown(); + }); + waitForLatch(latch, 5, "Timeout waiting for setupTest()."); + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch(TestApp.class, (String[])null)).start(); + waitForLatch(startupLatch, 10, "Timeout waiting for FX runtime to start"); + setupUI(); + } + + @AfterClass + public static void exit() { + Platform.runLater(() -> { + tabPane.getTabs().removeAll(); + stage.hide(); + }); + Platform.exit(); + } + + public static class TestApp extends Application { + @Override + public void start(Stage primaryStage) { + robot = com.sun.glass.ui.Application.GetApplication().createRobot(); + stage = primaryStage; + tabPane = new TabPane(); + tabPane.setTabDragPolicy(TabPane.TabDragPolicy.REORDER); + tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS); + scene = new Scene(tabPane, SCENE_WIDTH, SCENE_HEIGHT); + stage.setScene(scene); + stage.initStyle(StageStyle.UNDECORATED); + stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> + Platform.runLater(startupLatch::countDown)); + stage.setAlwaysOnTop(true); + stage.show(); + } + } + + public static void waitForLatch(CountDownLatch latch, int seconds, String msg) { + try { + if (!latch.await(seconds, TimeUnit.SECONDS)) { + fail(msg); + } + } catch (Exception ex) { + fail("Unexpected exception: " + ex); + } + } +}