TestBench and RadioButtongGroup

Hi,

I’m trying to emulate a click on a RadioButtonGroup in a TestBench UIUnit test.
I can not use setValue() on the component, because then I get isFromClient() == false in the ValueChangeListener, and I need to make a distinction between the event coming from the client or not.

How can “click” a radio button in a radiobuttongroup from a UI Unit test using TestBench, based on string value that matches the label?

Thank you
Kristof

Have you tried using the RadioButtonTester? It has a click method, that should fire a fromClient = true event.

However, it is a known issue, that several testers do not set the fromClient to true: ComponentEvent.isFromClient() is false despite using TestWrappers.test() in a SpringUIUnitTest · Issue #1814 · vaadin/testbench · GitHub

Looks like the problem is that RadioButton is not a public class, only RadioButtonGroup is, so I can’t create a RadioButtonTester from an instance of RadioButton in my test. Those are wrapped and hidden

There is a selectItem() on RadioButtonGroupTester, but this doesn’t trigger a clientSide event, it simply does setValue based on the label. So isFromClient is false in the valueChange handler.

Also, to make it even more complicated … RadioButtonGroupTester assumes the itemRenderer is used, and not a componentRenderer. So ideally RadioButtonGroupTester should pass on a value of whatever the RadioButtonGroup is using, which in my case is an enum with.

How it is rendered shouldn’t be a concern of RadioButtonGroupTester, right?

As a workaround to test you could try out to get the children of the radio button group, using Component#getChildren, filter them by their element tag and then map them using the test method. That should hopefully result in a list of radio button testers, for instance

group.getChildren()
        .filter(c -> "vaadin-radio-button".equals(c.getElement().getTag()))
        .map(this::test)
        .map(RadioButtonTester.class::cast)
        .toList();

Hi,

Thank you Stefan, for trying to help me out.

In order to find the correct RadioButtonTester, I set an ID on the component I create in the componentRenderer on the RadioButtonGroup.

Using the following (based on your code) I managed to find the right RadioButton to click.

private void clickRadioButton(Mode mode) {
        final RadioButtonGroup group = $view(RadioButtonGroup.class).first();
        group.getChildren()
                .filter(c -> "vaadin-radio-button".equals(c.getElement().getTag()))
                .map(this::test)
                .map(RadioButtonTester.class::cast)
                .filter((rbt) -> {
                    boolean found = false;
                    try {
                        rbt.find(Component.class).id(stringValueMode.name());
                        found = true;
                    } catch (NoSuchElementException ignored) {
                    }
                    return found;
                })
                .findFirst().ifPresent(RadioButtonTester::click);
    }

Problem now is, the click on the RadioButton doesn’t trigger a valueChangeEvent on the RadioButtonGroup. Looks like this isn’t propagated to the RadioButtonGroup it belongs to.

This is the click() implementation of RadioButtonTester

    /**
     * If the component is usable, send click to component as if it was from the
     * client.
     *
     * Checkbox status changes from unchecked to checked or vice versa.
     */
    public void click() {
        ensureComponentIsUsable();
        T radioButton = getComponent();
        ComponentUtil.fireEvent(radioButton, new ClickEvent<>(radioButton, true,
                0, 0, 0, 0, 0, 0, false, false, false, false));
        radioButton.setChecked(true);
    }

This, however made me realize … I can just fire the event! :smiley:

        final RadioButtonGroup group = $view(RadioButtonGroup.class).first();
        group.setValue(stringValueMode);
        ComponentUtil.fireEvent(group, new AbstractField.ComponentValueChangeEvent<>(group, group, null, true));

Why do something the easy way when you can spend a day trying it the hard way?

1 Like