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

Unhelpfull exception, NullPointerException: text must not be null #1801

Open
HerbertsVaadin opened this issue Jun 10, 2024 · 1 comment
Open

Comments

@HerbertsVaadin
Copy link

HerbertsVaadin commented Jun 10, 2024

I'm trying to query an extended Vaadin Button by attribute. Now, the extended button is a bit special, but the exception is quite unclear.
You'll see in my example myButton3 has no text set, and that is what causes the exception. The button itself is working just fine on frontend.

@Test
void testButtonExists() {
    navigate(RichTextButtonView.class);

    assertThat(findCustomerButtonByTranslation("tasty")).isNotNull();
    assertThat(findCustomerButtonByTranslation("xoxo")).isNotNull();
}


protected CustomerButton findCustomerButtonByTranslation(String translationKey) {
    return $(CustomerButton.class).withAttribute(TRANSLATION_ATTR, translationKey).single();
}

Exception:

java.lang.NullPointerException: text must not be null
	at com.vaadin.testbench.unit.internal.ComponentUtilsKt.getCaption(ComponentUtils.kt:382)
	at com.vaadin.testbench.unit.internal.ComponentUtilsKt.getCaption(ComponentUtils.kt:365)
	at com.vaadin.testbench.unit.internal.PrettyPrintTreeKt.toPrettyString(PrettyPrintTree.kt:102)
	at com.vaadin.testbench.unit.internal.PrettyPrintTree$Companion.ofVaadin(PrettyPrintTree.kt:63)
	at com.vaadin.testbench.unit.internal.PrettyPrintTree$Companion.ofVaadin(PrettyPrintTree.kt:65)
	at com.vaadin.testbench.unit.internal.PrettyPrintTree$Companion.ofVaadin(PrettyPrintTree.kt:65)
	at com.vaadin.testbench.unit.internal.PrettyPrintTree$Companion.ofVaadin(PrettyPrintTree.kt:65)
	at com.vaadin.testbench.unit.internal.PrettyPrintTree$Companion.ofVaadin(PrettyPrintTree.kt:65)
	at com.vaadin.testbench.unit.internal.PrettyPrintTreeKt.toPrettyTree(PrettyPrintTree.kt:72)
	at com.vaadin.testbench.unit.internal.LocatorKt._find(Locator.kt:186)
	at com.vaadin.testbench.unit.internal.LocatorKt._get(Locator.kt:144)
	at com.vaadin.testbench.unit.internal.LocatorKt._get(Locator.kt:167)
	at com.vaadin.testbench.unit.ComponentQuery.find(ComponentQuery.java:596)
	at com.vaadin.testbench.unit.ComponentQuery.single(ComponentQuery.java:468)
	at customer.CustomerTest.findButtonByTranslation(CustomerTest.java:67)
        .......

The extended button:

import com.vaadin.flow.component.button.Button;

public class CustomerButton extends Button {

	private RichTextSpan textContainer;

       	@Override
	public String getText() {
		return getTextContainer().getText();
	}

	@Override
	public void setText(String text) {
		getTextContainer().setText(text);
		setAriaLabel(getTextContainer().getText());
	}

	private RichTextSpan getTextContainer() {
		if (textContainer == null) {
			textContainer = new RichTextSpan();
			getElement().appendChild(textContainer.getElement());
		}

		return textContainer;
	}
}

RichTextSpan.java:

import com.vaadin.flow.component.html.Span;

public class RichTextSpan extends Span {
	
	public RichTextSpan() {
	}

	public RichTextSpan(String unsafeText) {
		setText(unsafeText);
	}


	@Override
	public String getText() {
		return getElement().getProperty("innerHTML");
	}

	@Override
	public void setText(String unsafeText) {
		String safeText = sanitize(unsafeText);
		getElement().setProperty("innerHTML", safeText);
		setWhiteSpace(WhiteSpace.BREAK_SPACES);
	}

	private String sanitize(String unsafeText) {
		// sanitizing logic here
		return unsafeText;
	}
}

The view, myButton3 is the one causing the problem:

package com.example.application.views.random;

import com.example.application.component.CustomerButton;
import com.example.application.views.MainLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import jakarta.annotation.security.PermitAll;

@PageTitle("Rich text button")
@Route(value = "rich-text-button", layout = MainLayout.class)
@PermitAll
public class RichTextButtonView extends VerticalLayout {

    public static final String TRANSLATION_ATTR = "data-translationKey";

    public RichTextButtonView() {
        var myButton = new CustomerButton();
        myButton.setText("I want it \n<b>tasty</b>");
        myButton.getElement().setAttribute(TRANSLATION_ATTR, "tasty");

        var myButton2 = new CustomerButton();
        myButton2.setText("I want it \n<b>super tasty</b>");
        myButton2.getElement().setAttribute(TRANSLATION_ATTR, "super tasty");

        var myButton3 = new CustomerButton();
        myButton3.getElement().setAttribute(TRANSLATION_ATTR, "no text");

        add(myButton, myButton2, myButton3);
    }
}

Test fails as expected, but doesn't doesn't provide useful message, and doesn't show the view structure because of the exception. Seems like pretty print should be able to handle text null cases. It seems to not to fall apart with not extended Button.

In the specific case, a the exception occurs when a button is not found, but there is a button somewhere with no text. Took me a while to find that button, since it was in a parent layout.

@mcollovati
Copy link
Contributor

The HasText.getText() Javadoc states that the method does not return null, so probably PrettyPrinter fails because it assumes it will get a non-null value.
Anyway, it makes sense that PrettyPrinter should not fail, even if the component does not fulfill Javadocs requirement. It should instead print the representation and possibly highlight unexpected values.

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