Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MenuItem can't be clicked on #662

Open
kulesc opened this issue Jun 26, 2019 · 7 comments
Open

MenuItem can't be clicked on #662

kulesc opened this issue Jun 26, 2019 · 7 comments

Comments

@kulesc
Copy link

kulesc commented Jun 26, 2019

Expected Behavior

I would like to test clicking on a menu item. I expected it to work this way:

new FxRobot().clickOn("#fileMenu").clickOn("#quitOption");

Actual Behavior

Test fails with an error:

org.testfx.api.FxRobotException: the query "#quitOption" returned no nodes.
	at org.testfx.api.FxRobot.queryVisibleNode(FxRobot.java:949)
	at org.testfx.api.FxRobot.pointOfVisibleNode(FxRobot.java:922)
	at org.testfx.api.FxRobot.clickOn(FxRobot.java:630)
	at org.testfx.api.FxRobot.clickOn(FxRobot.java:59)
	at org.testfx.api.FxRobotInterface.clickOn(FxRobotInterface.java:639)
	at rs.ac.bg.etf.ui.StorageManagerAppTest.quitFromMenu(StorageManagerAppTest.java:67)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

Specifications

  • Version: 4.0.15-alpha
  • Platform: MacOS Mojave v10.14.5

Example

FXML file looks like this:

<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml">
  <children>
    <MenuBar fx:id="mainMenu" VBox.vgrow="NEVER">
      <menus>
        <Menu fx:id="fileMenu" mnemonicParsing="false" text="File">
          <items>
            <MenuItem id="quitOption" mnemonicParsing="false" text="Quit" />
          </items>
        </Menu>
      </menus>
    </MenuBar>
      <BorderPane prefHeight="600.0" prefWidth="800.0">
         <center>
            <TableView fx:id="table" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
               <BorderPane.margin>
                  <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
               </BorderPane.margin>
            </TableView>
         </center>
         <top>
            <Label fx:id="tableHeadingLabel" text="All available items in the storage:" BorderPane.alignment="TOP_LEFT">
               <BorderPane.margin>
                  <Insets bottom="5.0" left="10.0" top="10.0" />
               </BorderPane.margin>
            </Label>
         </top>
      </BorderPane>
  </children>
</VBox>

Test code:

public class StorageManagerAppTest extends ApplicationTest {

	@Override
	public void start(Stage stage) throws Exception {
		Parent mainNode = FXMLLoader.load(StorageManagerApp.class.getResource("/MainPage.fxml"));
		stage.setScene(new Scene(mainNode));
		stage.show();
		stage.toFront();
	}

	@After
	public void tearDown() throws Exception {
		FxToolkit.hideStage();
		release(new KeyCode[] {});
		release(new MouseButton[] {});
	}

	@Test
	public void quitFromMenu() {
		new FxRobot().clickOn("#fileMenu").clickOn("#quitOption");
	}
}

I would appreciate any known workarounds. I have tried accessing element with bot fx:id and id but none if those options work.

@seggcsont
Copy link
Contributor

Have you tried waiting for the menu item before tries to click it?

@kulesc
Copy link
Author

kulesc commented Jun 26, 2019

Have you tried waiting for the menu item before tries to click it?

I didn't. Not sure how would I do it.

What I tried is to verify that it is there but it seems like query/lookup method can't fetch MenuItem. Maybe it is because it doesn't extend Node class.

@seggcsont
Copy link
Contributor

I would use something like:
`
FxRobot robot = new FxRobot();
robot.clickOn("#fileMenu");
WaitForAsyncUtils.waitFor(2, TimeUnit.SECONDS, () -> robot.lookup("#quitOption").matches(NodeQueryUtils.isVisible()).tryQuery().isPresent());

robot.clickOn("#quitOption");
`

Please correct me if there is a better way to do this.

@kulesc
Copy link
Author

kulesc commented Jun 26, 2019

I couldn't make your code compile so I tried the following code snippet

FxRobot robot = new FxRobot();
robot.clickOn("#fileMenu");
WaitForAsyncUtils.sleep(2, TimeUnit.SECONDS);

I noticed that robot doesn't even click on File option in MenuBar. It just moves a mouse there and does nothing. What I also tried is to create a Menu and MenuItems and give reference to clickOn method directly, but it seems it doesn't support clicking on these kind of elements, possibly because they do not extend Node class.

@seggcsont
Copy link
Contributor

seggcsont commented Jun 27, 2019

Hi,
I don't know what's wrong in your side, but your code without any modification works for me 20/20 times.
How do you start you test?

@kulesc
Copy link
Author

kulesc commented Jun 27, 2019

I run it from Eclipse as a JUnit test.

If I use your code I get this error message:
The method waitFor(long, TimeUnit, Future<T>) in the type WaitForAsyncUtils is not applicable for the arguments (int, TimeUnit, () -> {}).
and this:
The target type of this expression must be a functional interface.

@seggcsont
Copy link
Contributor

seggcsont commented Jun 27, 2019

FxRobot robot = new FxRobot();
robot.clickOn("#fileMenu");
WaitForAsyncUtils.waitFor(2, TimeUnit.SECONDS, () -> 
    robot.lookup("#quitOption").match(NodeQueryUtils.isVisible()).tryQuery().isPresent());
robot.clickOn("#quitOption");

This code works for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants