Programmatically fireEvent in TextField - JavaFX

Viewed 4621

Let's say a have a TextField

TextField tf = new TextField();

and I want to simulate the user pressing a key.

KeyEvent ke = new KeyEvent(KeyEvent.KEY_RELEASED, 
    KeyCode.A.toString(), KeyCode.A.toString(), 
    KeyCode.A, false, false, false, false);
tf.fireEvent(ke);

if I examine the text contents of tf, I will see this state hold true

tf.getText() == ""

What happened to my KeyEvent and why didn't the text equal "a"? I have tried this with KEY_RELEASED, KEY_PRESSED, and KEY_TYPED

Contained Example:

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;

import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

import java.util.concurrent.CountDownLatch;

import javax.swing.SwingUtilities;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class TextFieldExample {

    @Rule public JavaFXThreadingRule javafxRule = new JavaFXThreadingRule();
    @Test
    public void onlyAcceptValidInputs() {
        TextField tf = new TextField();
        KeyEvent ke = new KeyEvent(KeyEvent.KEY_RELEASED, 
                KeyCode.A.toString(), KeyCode.A.toString(), 
                KeyCode.A, false, false, false, false);
        tf.fireEvent(ke);
        Assert.assertEquals("A", tf.getText());
    }
}

class JavaFXThreadingRule implements TestRule {    
    /**
     * Flag for setting up the JavaFX, we only need to do this once for all tests.
     */
    private static boolean jfxIsSetup;

    @Override
    public Statement apply(Statement statement, Description description) {

        return new OnJFXThreadStatement(statement);
    }

    private static class OnJFXThreadStatement extends Statement {

        private final Statement statement;

        private OnJFXThreadStatement(Statement aStatement) {
            statement = aStatement;
        }

        private Throwable rethrownException = null;

        @Override
        public void evaluate() throws Throwable {

            if(!jfxIsSetup) {
                setupJavaFX();

                jfxIsSetup = true;
            }

            final CountDownLatch countDownLatch = new CountDownLatch(1);

            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        statement.evaluate();
                    } catch (Throwable e) {
                        rethrownException = e;
                    }
                    countDownLatch.countDown();
                }});

            countDownLatch.await();

            // if an exception was thrown by the statement during evaluation,
            // then re-throw it to fail the test
            if(rethrownException != null) {
                throw rethrownException;
            }
        }

        protected void setupJavaFX() throws InterruptedException {
            final CountDownLatch latch = new CountDownLatch(1);            
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    // initializes JavaFX environment
                    new JFXPanel();                    
                    latch.countDown();
                }
            });

            latch.await();
        }

    }
}
1 Answers
Related