From ad005e55db6f46d2d8acaa54d72e439ea27933f3 Mon Sep 17 00:00:00 2001 From: Sergey Vinogradov Date: Tue, 30 Jul 2024 11:13:31 +0300 Subject: [PATCH] feat: add i18n error message support for ComboBox, MultiSelectComboBox (#6474) --- .../ComboBoxBasicValidationPage.java | 4 + ...ultiSelectComboBoxBasicValidationPage.java | 5 + .../validation/ComboBoxBasicValidationIT.java | 8 ++ .../MultiSelectComboBoxBasicValidationIT.java | 9 ++ .../flow/component/combobox/ComboBox.java | 64 +++++++++++ .../flow/component/combobox/ComboBoxBase.java | 101 +++++++++++++++++- .../component/combobox/ComboBoxBaseI18n.java | 31 ++++++ .../combobox/MultiSelectComboBox.java | 16 +-- .../combobox/MultiSelectComboBoxI18n.java | 35 +++++- .../ComboBoxBasicValidationTest.java | 53 ++++++++- ...ultiSelectComboBoxBasicValidationTest.java | 54 +++++++++- 11 files changed, 363 insertions(+), 17 deletions(-) create mode 100644 vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBoxBaseI18n.java diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/main/java/com/vaadin/flow/component/combobox/test/validation/ComboBoxBasicValidationPage.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/main/java/com/vaadin/flow/component/combobox/test/validation/ComboBoxBasicValidationPage.java index a9f8b28ade7..766e4268fed 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/main/java/com/vaadin/flow/component/combobox/test/validation/ComboBoxBasicValidationPage.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/main/java/com/vaadin/flow/component/combobox/test/validation/ComboBoxBasicValidationPage.java @@ -10,9 +10,13 @@ public class ComboBoxBasicValidationPage extends AbstractValidationPage> { public static final String REQUIRED_BUTTON = "required-button"; + public static final String REQUIRED_ERROR_MESSAGE = "Field is required"; public static final String ENABLE_CUSTOM_VALUE_BUTTON = "enable-custom-value-button"; public ComboBoxBasicValidationPage() { + testField.setI18n(new ComboBox.ComboBoxI18n() + .setRequiredErrorMessage(REQUIRED_ERROR_MESSAGE)); + add(createButton(REQUIRED_BUTTON, "Enable required", event -> { testField.setRequired(true); })); diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/main/java/com/vaadin/flow/component/combobox/test/validation/MultiSelectComboBoxBasicValidationPage.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/main/java/com/vaadin/flow/component/combobox/test/validation/MultiSelectComboBoxBasicValidationPage.java index e05f0467352..57a0c806982 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/main/java/com/vaadin/flow/component/combobox/test/validation/MultiSelectComboBoxBasicValidationPage.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/main/java/com/vaadin/flow/component/combobox/test/validation/MultiSelectComboBoxBasicValidationPage.java @@ -1,6 +1,7 @@ package com.vaadin.flow.component.combobox.test.validation; import com.vaadin.flow.component.combobox.MultiSelectComboBox; +import com.vaadin.flow.component.combobox.MultiSelectComboBoxI18n; import com.vaadin.flow.router.Route; import com.vaadin.tests.validation.AbstractValidationPage; @@ -10,9 +11,13 @@ public class MultiSelectComboBoxBasicValidationPage extends AbstractValidationPage> { public static final String REQUIRED_BUTTON = "required-button"; + public static final String REQUIRED_ERROR_MESSAGE = "Field is required"; public static final String ENABLE_CUSTOM_VALUE_BUTTON = "enable-custom-value-button"; public MultiSelectComboBoxBasicValidationPage() { + testField.setI18n(new MultiSelectComboBoxI18n() + .setRequiredErrorMessage(REQUIRED_ERROR_MESSAGE)); + add(createButton(REQUIRED_BUTTON, "Enable required", event -> { testField.setRequired(true); })); diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/test/java/com/vaadin/flow/component/combobox/test/validation/ComboBoxBasicValidationIT.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/test/java/com/vaadin/flow/component/combobox/test/validation/ComboBoxBasicValidationIT.java index 9a6ea052111..569da7120d3 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/test/java/com/vaadin/flow/component/combobox/test/validation/ComboBoxBasicValidationIT.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/test/java/com/vaadin/flow/component/combobox/test/validation/ComboBoxBasicValidationIT.java @@ -8,6 +8,7 @@ import static com.vaadin.flow.component.combobox.test.validation.ComboBoxBasicValidationPage.ENABLE_CUSTOM_VALUE_BUTTON; import static com.vaadin.flow.component.combobox.test.validation.ComboBoxBasicValidationPage.REQUIRED_BUTTON; +import static com.vaadin.flow.component.combobox.test.validation.ComboBoxBasicValidationPage.REQUIRED_ERROR_MESSAGE; @TestPath("vaadin-combo-box/validation/basic") public class ComboBoxBasicValidationIT @@ -17,6 +18,7 @@ public class ComboBoxBasicValidationIT public void fieldIsInitiallyValid() { assertClientValid(); assertServerValid(); + assertErrorMessage(null); } @Test @@ -25,6 +27,7 @@ public void triggerBlur_assertValidity() { assertValidationCount(0); assertServerValid(); assertClientValid(); + assertErrorMessage(null); } @Test @@ -35,6 +38,7 @@ public void required_triggerBlur_assertValidity() { assertValidationCount(0); assertServerValid(); assertClientValid(); + assertErrorMessage(null); } @Test @@ -45,11 +49,13 @@ public void required_changeValue_assertValidity() { assertValidationCount(1); assertServerValid(); assertClientValid(); + assertErrorMessage(""); testField.clear(); assertValidationCount(1); assertServerInvalid(); assertClientInvalid(); + assertErrorMessage(REQUIRED_ERROR_MESSAGE); } @Test @@ -60,6 +66,7 @@ public void required_enterCustomValue_assertValidity() { assertValidationCount(0); assertServerValid(); assertClientValid(); + assertErrorMessage(null); } @Test @@ -71,6 +78,7 @@ public void required_customValuesAllowed_enterCustomValue_assertValidity() { assertValidationCount(1); assertServerValid(); assertClientValid(); + assertErrorMessage(""); } @Test diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/test/java/com/vaadin/flow/component/combobox/test/validation/MultiSelectComboBoxBasicValidationIT.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/test/java/com/vaadin/flow/component/combobox/test/validation/MultiSelectComboBoxBasicValidationIT.java index e19246a17fd..266adaabe06 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/test/java/com/vaadin/flow/component/combobox/test/validation/MultiSelectComboBoxBasicValidationIT.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow-integration-tests/src/test/java/com/vaadin/flow/component/combobox/test/validation/MultiSelectComboBoxBasicValidationIT.java @@ -8,6 +8,7 @@ import static com.vaadin.flow.component.combobox.test.validation.MultiSelectComboBoxBasicValidationPage.ENABLE_CUSTOM_VALUE_BUTTON; import static com.vaadin.flow.component.combobox.test.validation.MultiSelectComboBoxBasicValidationPage.REQUIRED_BUTTON; +import static com.vaadin.flow.component.combobox.test.validation.MultiSelectComboBoxBasicValidationPage.REQUIRED_ERROR_MESSAGE; @TestPath("vaadin-multi-select-combo-box/validation/basic") public class MultiSelectComboBoxBasicValidationIT @@ -17,6 +18,7 @@ public class MultiSelectComboBoxBasicValidationIT public void fieldIsInitiallyValid() { assertClientValid(); assertServerValid(); + assertErrorMessage(null); } @Test @@ -25,6 +27,7 @@ public void triggerBlur_assertValidity() { assertValidationCount(0); assertServerValid(); assertClientValid(); + assertErrorMessage(null); } @Test @@ -35,6 +38,7 @@ public void required_triggerBlur_assertValidity() { assertValidationCount(0); assertServerValid(); assertClientValid(); + assertErrorMessage(null); } @Test @@ -45,11 +49,13 @@ public void required_changeValue_assertValidity() { assertValidationCount(1); assertServerValid(); assertClientValid(); + assertErrorMessage(""); testField.deselectAll(); assertValidationCount(1); assertServerInvalid(); assertClientInvalid(); + assertErrorMessage(REQUIRED_ERROR_MESSAGE); } @Test @@ -60,6 +66,7 @@ public void required_enterCustomValue_assertValidity() { assertValidationCount(0); assertServerValid(); assertClientValid(); + assertErrorMessage(null); } @Test @@ -71,11 +78,13 @@ public void required_customValuesAllowed_enterCustomValue_assertValidity() { assertValidationCount(1); assertServerValid(); assertClientValid(); + assertErrorMessage(""); testField.deselectAll(); assertValidationCount(1); assertServerInvalid(); assertClientInvalid(); + assertErrorMessage(REQUIRED_ERROR_MESSAGE); } @Test diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBox.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBox.java index 2d16537c12f..90f49cebdee 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBox.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBox.java @@ -18,6 +18,8 @@ import java.io.Serializable; import java.util.Collection; import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; import java.util.stream.Stream; import com.vaadin.flow.component.HasSize; @@ -353,4 +355,66 @@ public void setOverlayWidth(float width, Unit unit) { Objects.requireNonNull(unit, "Unit can not be null"); setOverlayWidth(HasSize.getCssSize(width, unit)); } + + /** + * Gets the internationalization object previously set for this component. + *

+ * NOTE: Updating the instance that is returned from this method will not + * update the component if not set again using + * {@link #setI18n(ComboBoxI18n)} + * + * @return the i18n object or {@code null} if no i18n object has been set + */ + public ComboBoxI18n getI18n() { + return (ComboBoxI18n) super.getI18n(); + } + + /** + * Sets the internationalization object for this component. + * + * @param i18n + * the i18n object, not {@code null} + */ + public void setI18n(ComboBoxI18n i18n) { + super.setI18n(i18n); + } + + /** + * The internationalization properties for {@link ComboBox}. + */ + public static class ComboBoxI18n implements ComboBoxBaseI18n { + + private String requiredErrorMessage; + + /** + * Gets the error message displayed when the field is required but + * empty. + * + * @return the error message or {@code null} if not set + * @see ComboBox#isRequiredIndicatorVisible() + * @see ComboBox#setRequiredIndicatorVisible(boolean) + */ + public String getRequiredErrorMessage() { + return requiredErrorMessage; + } + + /** + * Sets the error message to display when the field is required but + * empty. + *

+ * Note, custom error messages set with + * {@link ComboBox#setErrorMessage(String)} take priority over i18n + * error messages. + * + * @param errorMessage + * the error message or {@code null} to clear it + * @return this instance for method chaining + * @see ComboBox#isRequiredIndicatorVisible() + * @see ComboBox#setRequiredIndicatorVisible(boolean) + */ + public ComboBoxI18n setRequiredErrorMessage(String errorMessage) { + requiredErrorMessage = errorMessage; + return this; + } + } } diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBoxBase.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBoxBase.java index 99cb9212725..a587347951a 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBoxBase.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBoxBase.java @@ -44,6 +44,7 @@ import com.vaadin.flow.component.shared.InputField; import com.vaadin.flow.component.shared.ValidationUtil; import com.vaadin.flow.data.binder.HasValidator; +import com.vaadin.flow.data.binder.ValidationResult; import com.vaadin.flow.data.provider.BackEndDataProvider; import com.vaadin.flow.data.provider.CallbackDataProvider; import com.vaadin.flow.data.provider.CompositeDataGenerator; @@ -69,6 +70,7 @@ import java.util.Locale; import java.util.Objects; import java.util.Optional; +import java.util.function.Function; /** * Provides base functionality for combo box related components, such as @@ -123,8 +125,13 @@ public void remove() { private final ComboBoxDataController dataController; private int customValueListenersCount; + private ComboBoxBaseI18n i18n; + private boolean manualValidationEnabled = false; + private String customErrorMessage; + private String constraintErrorMessage; + /** * Constructs a new ComboBoxBase instance * @@ -184,6 +191,45 @@ public Locale get() { addValueChangeListener(e -> validate()); } + /** + * Sets an error message to display for all constraint violations. + *

+ * This error message takes priority over i18n error messages when both are + * set. + * + * @param errorMessage + * the error message to set, or {@code null} to clear + * + */ + @Override + public void setErrorMessage(String errorMessage) { + customErrorMessage = errorMessage; + updateErrorMessage(); + } + + /** + * Gets the error message displayed for all constraint violations. + * + * @return the error message + */ + @Override + public String getErrorMessage() { + return customErrorMessage; + } + + private void setConstraintErrorMessage(String errorMessage) { + constraintErrorMessage = errorMessage; + updateErrorMessage(); + } + + private void updateErrorMessage() { + String errorMessage = constraintErrorMessage; + if (customErrorMessage != null && !customErrorMessage.isEmpty()) { + errorMessage = customErrorMessage; + } + getElement().setProperty("errorMessage", errorMessage); + } + /** * Whether the component should automatically receive focus when the page * loads. @@ -1190,13 +1236,29 @@ public void setManualValidation(boolean enabled) { this.manualValidationEnabled = enabled; } + /** + * Validates the current value against the constraints and sets the + * {@code invalid} property and the {@code errorMessage} property based on + * the result. If a custom error message is provided with + * {@link #setErrorMessage(String)}, it is used. Otherwise, the error + * message defined in the i18n object is used. + *

+ * The method does nothing if the manual validation mode is enabled. + */ protected void validate() { - if (!this.manualValidationEnabled) { - boolean isInvalid = ValidationUtil.validateRequiredConstraint("", - isRequiredIndicatorVisible(), getValue(), getEmptyValue()) - .isError(); + if (this.manualValidationEnabled) { + return; + } - setInvalid(isInvalid); + ValidationResult result = ValidationUtil.validateRequiredConstraint( + getI18nErrorMessage(ComboBoxBaseI18n::getRequiredErrorMessage), + isRequiredIndicatorVisible(), getValue(), getEmptyValue()); + if (result.isError()) { + setInvalid(true); + setConstraintErrorMessage(result.getErrorMessage()); + } else { + setInvalid(false); + setConstraintErrorMessage(""); } } @@ -1223,4 +1285,33 @@ public String getDetail() { return detail; } } + + /** + * Gets the internationalization object previously set for this component. + *

+ * NOTE: Updating the instance that is returned from this method will not + * update the component if not set again using + * {@link #setI18n(ComboBoxBaseI18n)} + * + * @return the i18n object or {@code null} if no i18n object has been set + */ + protected ComboBoxBaseI18n getI18n() { + return i18n; + } + + /** + * Sets the internationalization object for this component. + * + * @param i18n + * the i18n object, not {@code null} + */ + protected void setI18n(ComboBoxBaseI18n i18n) { + this.i18n = Objects.requireNonNull(i18n, + "The i18n properties object should not be null"); + } + + private String getI18nErrorMessage( + Function getter) { + return Optional.ofNullable(i18n).map(getter).orElse(""); + } } diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBoxBaseI18n.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBoxBaseI18n.java new file mode 100644 index 00000000000..e7ee87eaf89 --- /dev/null +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/ComboBoxBaseI18n.java @@ -0,0 +1,31 @@ + +/* + * Copyright 2000-2024 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.combobox; + +import java.io.Serializable; + +/** + * The internationalization properties for {@link ComboBoxBase}. + */ +public interface ComboBoxBaseI18n extends Serializable { + /** + * Gets the error message displayed when the field is required but empty. + * + * @return the error message or {@code null} if not set + */ + String getRequiredErrorMessage(); +} diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/MultiSelectComboBox.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/MultiSelectComboBox.java index ba6fef9f705..4f7493e6495 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/MultiSelectComboBox.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/MultiSelectComboBox.java @@ -84,7 +84,6 @@ public class MultiSelectComboBox HasThemeVariant { private final MultiSelectComboBoxSelectionModel selectionModel; - private MultiSelectComboBoxI18n i18n; private AutoExpandMode autoExpand; /** @@ -241,8 +240,8 @@ public MultiSelectComboBox(String label, protected void onAttach(AttachEvent attachEvent) { super.onAttach(attachEvent); - if (i18n != null) { - this.updateI18n(); + if (getI18n() != null) { + updateI18n(); } } @@ -540,7 +539,7 @@ public void setKeepFilter(boolean keepFilter) { * @return the i18n object or {@code null} if no i18n object has been set */ public MultiSelectComboBoxI18n getI18n() { - return i18n; + return (MultiSelectComboBoxI18n) super.getI18n(); } /** @@ -550,8 +549,7 @@ public MultiSelectComboBoxI18n getI18n() { * the i18n object, not {@code null} */ public void setI18n(MultiSelectComboBoxI18n i18n) { - this.i18n = Objects.requireNonNull(i18n, - "The i18n properties object should not be null"); + super.setI18n(i18n); updateI18n(); } @@ -561,12 +559,16 @@ public void setI18n(MultiSelectComboBoxI18n i18n) { * settings of the web component. */ private void updateI18n() { - JsonObject i18nJson = (JsonObject) JsonSerializer.toJson(this.i18n); + JsonObject i18nJson = (JsonObject) JsonSerializer.toJson(getI18n()); // Remove null values so that we don't overwrite existing WC // translations with empty ones removeNullValuesFromJsonObject(i18nJson); + // Remove the error message properties because they aren't used on + // the client-side. + i18nJson.remove("requiredErrorMessage"); + // Assign new I18N object to WC, by merging the existing // WC I18N, and the values from the new I18n instance, // into an empty object diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/MultiSelectComboBoxI18n.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/MultiSelectComboBoxI18n.java index a74e59f0cd2..9a7d0379299 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/MultiSelectComboBoxI18n.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/main/java/com/vaadin/flow/component/combobox/MultiSelectComboBoxI18n.java @@ -15,17 +15,46 @@ */ package com.vaadin.flow.component.combobox; -import java.io.Serializable; - /** * Class for localization of the {@link MultiSelectComboBox} */ -public class MultiSelectComboBoxI18n implements Serializable { +public class MultiSelectComboBoxI18n implements ComboBoxBaseI18n { private String cleared; private String focused; private String selected; private String deselected; private String total; + private String requiredErrorMessage; + + /** + * Gets the error message displayed when the field is required but empty. + * + * @return the error message or {@code null} if not set + * @see MultiSelectComboBox#isRequiredIndicatorVisible() + * @see MultiSelectComboBox#setRequiredIndicatorVisible(boolean) + */ + public String getRequiredErrorMessage() { + return requiredErrorMessage; + } + + /** + * Sets the error message to display when the field is required but empty. + *

+ * Note, custom error messages set with + * {@link MultiSelectComboBox#setErrorMessage(String)} take priority over + * i18n error messages. + * + * @param errorMessage + * the error message or {@code null} to clear it + * @return this instance for method chaining + * @see MultiSelectComboBox#isRequiredIndicatorVisible() + * @see MultiSelectComboBox#setRequiredIndicatorVisible(boolean) + */ + public MultiSelectComboBoxI18n setRequiredErrorMessage( + String errorMessage) { + requiredErrorMessage = errorMessage; + return this; + } /** * The text that is announced by screen readers when the clear button is diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/test/java/com/vaadin/flow/component/combobox/validation/ComboBoxBasicValidationTest.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/test/java/com/vaadin/flow/component/combobox/validation/ComboBoxBasicValidationTest.java index 08129cb82d6..d555f118dcf 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/test/java/com/vaadin/flow/component/combobox/validation/ComboBoxBasicValidationTest.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/test/java/com/vaadin/flow/component/combobox/validation/ComboBoxBasicValidationTest.java @@ -15,12 +15,63 @@ */ package com.vaadin.flow.component.combobox.validation; +import org.junit.Assert; +import org.junit.Test; + import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.tests.validation.AbstractBasicValidationTest; public class ComboBoxBasicValidationTest extends AbstractBasicValidationTest, String> { + @Test + public void required_validate_emptyErrorMessageDisplayed() { + testField.setRequiredIndicatorVisible(true); + testField.setValue("foo"); + testField.setValue(null); + Assert.assertEquals("", getErrorMessageProperty()); + } + + @Test + public void required_setI18nErrorMessage_validate_i18nErrorMessageDisplayed() { + testField.setRequiredIndicatorVisible(true); + testField.setI18n(new ComboBox.ComboBoxI18n() + .setRequiredErrorMessage("Field is required")); + testField.setValue("foo"); + testField.setValue(null); + Assert.assertEquals("Field is required", getErrorMessageProperty()); + } + + @Test + public void setI18nAndCustomErrorMessage_validate_customErrorMessageDisplayed() { + testField.setRequiredIndicatorVisible(true); + testField.setI18n(new ComboBox.ComboBoxI18n() + .setRequiredErrorMessage("Field is required")); + testField.setErrorMessage("Custom error message"); + testField.setValue("foo"); + testField.setValue(null); + Assert.assertEquals("Custom error message", getErrorMessageProperty()); + } + + @Test + public void setI18nAndCustomErrorMessage_validate_removeCustomErrorMessage_i18nErrorMessageDisplayed() { + testField.setRequiredIndicatorVisible(true); + testField.setI18n(new ComboBox.ComboBoxI18n() + .setRequiredErrorMessage("Field is required")); + testField.setErrorMessage("Custom error message"); + testField.setValue("foo"); + testField.setValue(null); + testField.setErrorMessage(""); + Assert.assertEquals("Field is required", getErrorMessageProperty()); + } + + @Override protected ComboBox createTestField() { - return new ComboBox(); + ComboBox comboBox = new ComboBox<>(); + comboBox.setItems("foo"); + return comboBox; + } + + private String getErrorMessageProperty() { + return testField.getElement().getProperty("errorMessage"); } } diff --git a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/test/java/com/vaadin/flow/component/combobox/validation/MultiSelectComboBoxBasicValidationTest.java b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/test/java/com/vaadin/flow/component/combobox/validation/MultiSelectComboBoxBasicValidationTest.java index 523e7fe3ace..8ff4097e577 100644 --- a/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/test/java/com/vaadin/flow/component/combobox/validation/MultiSelectComboBoxBasicValidationTest.java +++ b/vaadin-combo-box-flow-parent/vaadin-combo-box-flow/src/test/java/com/vaadin/flow/component/combobox/validation/MultiSelectComboBoxBasicValidationTest.java @@ -17,12 +17,64 @@ import java.util.Set; +import org.junit.Assert; +import org.junit.Test; + import com.vaadin.flow.component.combobox.MultiSelectComboBox; +import com.vaadin.flow.component.combobox.MultiSelectComboBoxI18n; import com.vaadin.tests.validation.AbstractBasicValidationTest; public class MultiSelectComboBoxBasicValidationTest extends AbstractBasicValidationTest, Set> { + @Test + public void required_validate_emptyErrorMessageDisplayed() { + testField.setRequiredIndicatorVisible(true); + testField.setValue(Set.of("foo")); + testField.setValue(Set.of()); + Assert.assertEquals("", getErrorMessageProperty()); + } + + @Test + public void required_setI18nErrorMessage_validate_i18nErrorMessageDisplayed() { + testField.setRequiredIndicatorVisible(true); + testField.setI18n(new MultiSelectComboBoxI18n() + .setRequiredErrorMessage("Field is required")); + testField.setValue(Set.of("foo")); + testField.setValue(Set.of()); + Assert.assertEquals("Field is required", getErrorMessageProperty()); + } + + @Test + public void setI18nAndCustomErrorMessage_validate_customErrorMessageDisplayed() { + testField.setRequiredIndicatorVisible(true); + testField.setI18n(new MultiSelectComboBoxI18n() + .setRequiredErrorMessage("Field is required")); + testField.setErrorMessage("Custom error message"); + testField.setValue(Set.of("foo")); + testField.setValue(Set.of()); + Assert.assertEquals("Custom error message", getErrorMessageProperty()); + } + + @Test + public void setI18nAndCustomErrorMessage_validate_removeCustomErrorMessage_i18nErrorMessageDisplayed() { + testField.setRequiredIndicatorVisible(true); + testField.setI18n(new MultiSelectComboBoxI18n() + .setRequiredErrorMessage("Field is required")); + testField.setErrorMessage("Custom error message"); + testField.setValue(Set.of("foo")); + testField.setValue(Set.of()); + testField.setErrorMessage(""); + Assert.assertEquals("Field is required", getErrorMessageProperty()); + } + + @Override protected MultiSelectComboBox createTestField() { - return new MultiSelectComboBox(); + MultiSelectComboBox comboBox = new MultiSelectComboBox<>(); + comboBox.setItems("foo"); + return comboBox; + } + + private String getErrorMessageProperty() { + return testField.getElement().getProperty("errorMessage"); } }