javajavafxjava-8javafx-8testfx

Test passing on TestFX, but not in headless mode


I am using TestFX to test selecting multiple items in a ListView using the Ctrl key, then clicking a button, which generates an alert dialog whose content is based on the items selected.

press(KeyCode.CONTROL);
clickOn((Node) lookup(hasText("Item 0")).query());
verifyThat((Node) lookup(hasText("Item 0")).query(), Node::isFocused);
clickOn((Node) lookup(hasText("Item 1")).query());
verifyThat((Node) lookup(hasText("Item 1")).query(), Node::isFocused);
clickOn((Node) lookup(hasText("Item 2")).query());
verifyThat((Node) lookup(hasText("Item 2")).query(), Node::isFocused);
release(KeyCode.CONTROL);

clickOn("actionButton");
alertDialogHasHeaderAndContent("Items selected: 3"); // my own function

In headful mode

The tests all pass.

In headless mode

The three verifyThat tests all pass, but when it clicks on the button and verifies that the resulting alert dialog is correct, it isn't; the alert generated is as if only one item from the list was selected.

It results in:

org.junit.ComparisonFailure: 
Expected :Items selected: 3
Actual   :Items selected: 1

Here is alertDialogHasHeaderAndContent for completeness:

/**
 * Checks the current alert dialog displayed (on the top of the window stack) has the expected contents.
 *
 * From https://stackoverflow.com/a/48654878/8355496
 * Licenced under cc by-sa 3.0 with attribution required https://creativecommons.org/licenses/by-sa/3.0/
 * @param expectedHeader Expected header of the dialog
 * @param expectedContent Expected content of the dialog
 */
private void alertDialogHasHeaderAndContent(final String expectedHeader, final String expectedContent) {
    final Stage actualAlertDialog = getTopModalStage();
    assertNotNull(actualAlertDialog);

    final DialogPane dialogPane = (DialogPane) actualAlertDialog.getScene().getRoot();
    assertEquals(expectedHeader, dialogPane.getHeaderText());
    assertEquals(expectedContent, dialogPane.getContentText());
}

/**
 * Get the top modal window.
 *
 * Adapted from https://stackoverflow.com/a/48654878/8355496
 * Licenced under cc by-sa 3.0 with attribution required https://creativecommons.org/licenses/by-sa/3.0/
 * @return the top modal window
 */
private Stage getTopModalStage() {
    // Get a list of windows but ordered from top[0] to bottom[n] ones.
    // It is needed to get the first found modal window.
    final List<Window> allWindows = new ArrayList<>(new FxRobot().robotContext().getWindowFinder().listWindows());
    Collections.reverse(allWindows);

    return (Stage) allWindows
            .stream()
            .filter(window -> window instanceof Stage)
            .findFirst()
            .orElse(null);
}

Solution

  • This is an issue with Monocole. See https://github.com/TestFX/TestFX/issues/566 for more information.