title: TestFx - Can't access login dialog
body: <p>I have a simple javafx application, where, right after stage.show(), I'm calling login dialog. When I run tests, they does not start to do their work until the login dialog is filled and confirmed manually. For test purposes, I tried to display another dialog after clicking on a button on stage and there were no problems with manipulating it through testFx. The only problem is with the initial login dialog. Is there a way to workaround this behavior, or am I doing something wrong?</p>
  
  <p>Test scenario:</p>
  
  <p>MainApp.java </p>
  
  <pre><code>package cz.mono.monofx;
  
  import cz.mono.monofx.fxml.LoginDialog;
  import cz.mono.monofx.fxml.ScreensController;
  import java.util.Optional;
  import javafx.application.Application;
  import static javafx.application.Application.launch;
  import javafx.scene.Group;
  import javafx.scene.Scene;
  import javafx.stage.Stage;
  import javafx.util.Pair;
  
  
  public class MainApp extends Application {
  
      public static final String SCREEN1 = "scene";
      private final String screen1fxml = "/fxml/Scene.fxml";
      public static final String SCREEN2 = "scene2";
      private final String screen2fxml = "/fxml/Scene2.fxml";
  
      @Override
      public void start(Stage stage) throws Exception {
  
          ScreensController mainContainer = new ScreensController();
          mainContainer.loadScreen(SCREEN1, screen1fxml);
          mainContainer.loadScreen(SCREEN2, screen2fxml);
  
          mainContainer.setScreen(SCREEN1);
  
          Group root = new Group(); 
          root.getChildren().addAll(mainContainer);
  
          Scene scene = new Scene(root);
          scene.getStylesheets().add("/styles/Styles.css");
  
          stage.setTitle("Aplipikacka");
          stage.setScene(scene);
          stage.show();
  
          LoginDialog login = new LoginDialog();
          Optional &lt;Pair&lt;String, String&gt;&gt; result = login.getResult();
      }
  
      /**
       * The main() method is ignored in correctly deployed JavaFX application.
       * main() serves only as fallback in case the application can not be
       * launched through deployment artifacts, e.g., in IDEs with limited FX
       * support. NetBeans ignores main().
       *
       * @param args the command line arguments
       */
      public static void main(String[] args) {
          launch(args);
      }
  
  }
  </code></pre>
  
  <p>TestFxBase.java </p>
  
  <pre><code>    package cz.mono.monofx.test;
  
  import cz.mono.monofx.MainApp;
  import java.util.concurrent.TimeoutException;
  import javafx.scene.Node;
  import javafx.scene.input.KeyCode;
  import javafx.scene.input.MouseButton;
  import javafx.stage.Stage;
  import org.junit.After;
  import org.junit.Before;
  import org.testfx.api.FxToolkit;
  import org.testfx.framework.junit.ApplicationTest;
  
  public class TestFxBase extends ApplicationTest {
  
      @Before
      public void setUpClass() throws Exception {
          ApplicationTest.launch(MainApp.class);
      }
  
      @After
      public void afterEachTest() throws TimeoutException {
          FxToolkit.hideStage();
          release(new KeyCode[]{});
          release(new MouseButton[]{});
      }
  
      //Helper method to retrieve javafx components
      public &lt;T extends Node&gt; T find(String query) {
          return (T) lookup(query).queryAll().iterator().next();
      } 
  
      @Override
      public void start(Stage stage) {
          stage.show();
      }
  }
  </code></pre>
  
  <p>SimpleTest.java</p>
  
  <pre><code>    package cz.mono.monofx.test;
  
  import static javafx.scene.input.KeyCode.TAB;
  import org.junit.Test;
  
  public class ValidationTest extends TestFxBase {
  
      @Test
      public void verifyLogin() {
          clickOn("#dialogButton");
          sleep(1000);
          type(TAB);
          sleep(1000);
          type(TAB);
          sleep(1000);
      }
  }
  </code></pre>
  
  <p>LoginDialog.java</p>
  
  <pre><code>package cz.mono.monofx.fxml;
  
  import java.util.Optional;
  import javafx.application.Platform;
  import javafx.beans.binding.Bindings;
  import javafx.beans.binding.BooleanBinding;
  import javafx.geometry.Insets;
  import javafx.scene.Node;
  import javafx.scene.control.ButtonBar.ButtonData;
  import javafx.scene.control.ButtonType;
  import javafx.scene.control.Dialog;
  import javafx.scene.control.Label;
  import javafx.scene.control.PasswordField;
  import javafx.scene.control.TextField;
  import javafx.scene.layout.GridPane;
  import javafx.util.Pair;
  
  public class LoginDialog {
  
      private Dialog&lt;Pair&lt;String, String&gt;&gt; dialog;
      private TextField username;
      private PasswordField password;
      private Optional&lt;Pair&lt;String, String&gt;&gt; result;
  
      public LoginDialog() {
          dialog = new Dialog&lt;&gt;();
          dialog.setTitle("Login");
          dialog.setHeaderText("Provide correct login informations.");
  
          username = new TextField();
          username.setPrefSize(150, 30);
          username.setPromptText("username");
          username.setId("username");
  
          //Request focus on username by default
          Platform.runLater(()-&gt; username.requestFocus());
  
          password = new PasswordField();
          password.setPrefSize(150, 30);
          password.setPromptText("password");
          password.setId("password");
  
          ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
          dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);
  
          Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
          loginButton.setId("loginButton");
          BooleanBinding bb = Bindings.createBooleanBinding(()-&gt; username.getText().isEmpty() || password.getText().isEmpty(), username.textProperty(), password.textProperty());
          loginButton.disableProperty().bind(bb);
  
          GridPane grid = new GridPane();
          grid.setVgap(10);
          grid.setHgap(10);
          grid.setPadding(new Insets(20, 150, 10, 10));
  
          grid.add(new Label("Username: "), 0, 0);
          grid.add(username, 0, 1);
          grid.add(new Label("Password"), 1, 0);
          grid.add(password, 1, 1);
  
          dialog.getDialogPane().setContent(grid);
  
          // Convert the result to a username-password-pair when the login button is clicked.
          dialog.setResultConverter(dialogButton -&gt; {
              if (dialogButton == loginButtonType) {
                  return new Pair&lt;&gt;(username.getText(), password.getText());
              }
              return null;
          });
  
          result = dialog.showAndWait();
          result.ifPresent(usernamePassword -&gt; {
              System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
          });
          if (!result.isPresent()) {
              System.exit(0);
          };
  
      }
  
      /**
       * @return the result
       */
      public Optional&lt;Pair&lt;String, String&gt;&gt; getResult() {
          return result;
      }
  }
  </code></pre>