Skip to content

Commit

Permalink
feat: add HasValidator and Binder validation tests to Checkbox
Browse files Browse the repository at this point in the history
  • Loading branch information
web-padawan committed Apr 10, 2024
1 parent a86bd44 commit 8d81583
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.vaadin.flow.component.checkbox.tests.validation;

import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.router.Route;
import com.vaadin.tests.validation.AbstractValidationPage;

@Route("vaadin-checkbox/validation/binder")
public class CheckboxBinderValidationPage
extends AbstractValidationPage<Checkbox> {

public static final String REQUIRED_ERROR_MESSAGE = "The field is required";

public static class Bean {
private Boolean property;

public Boolean getProperty() {
return property;
}

public void setProperty(Boolean property) {
this.property = property;
}
}

protected Binder<Bean> binder;

public CheckboxBinderValidationPage() {
super();

binder = new Binder<>(Bean.class);
binder.forField(testField).asRequired(REQUIRED_ERROR_MESSAGE)
.bind("property");
binder.addStatusChangeListener(event -> {
incrementServerValidationCounter();
});
}

@Override
protected Checkbox createTestField() {
return new Checkbox();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.vaadin.flow.component.checkbox.tests.validation;

import com.vaadin.flow.component.checkbox.testbench.CheckboxElement;
import com.vaadin.flow.testutil.TestPath;
import com.vaadin.tests.validation.AbstractValidationIT;
import org.junit.Test;
import org.openqa.selenium.Keys;

import static com.vaadin.flow.component.checkbox.tests.validation.BinderValidationPage.REQUIRED_ERROR_MESSAGE;

@TestPath("vaadin-checkbox/validation/binder")
public class CheckboxBinderValidationIT
extends AbstractValidationIT<CheckboxElement> {

@Test
public void fieldIsInitiallyValid() {
assertClientValid();
assertServerValid();
assertErrorMessage(null);
}

@Test
public void required_triggerBlur_assertValidity() {
testField.sendKeys(Keys.TAB);
assertValidationCount(0);
assertServerValid();
assertClientValid();
}

@Test
public void required_changeValue_assertValidity() {
testField.setChecked(true);
assertValidationCount(1);
assertServerValid();
assertClientValid();

testField.setChecked(false);
assertValidationCount(1);
assertServerInvalid();
assertClientInvalid();
assertErrorMessage(REQUIRED_ERROR_MESSAGE);
}

@Override
protected CheckboxElement getTestField() {
return $(CheckboxElement.class).first();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.vaadin.flow.component.shared.HasValidationProperties;
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.binder.Validator;
import com.vaadin.flow.dom.ElementConstants;
Expand All @@ -58,7 +59,7 @@
@JsModule("@vaadin/checkbox/src/vaadin-checkbox.js")
public class Checkbox extends AbstractSinglePropertyField<Checkbox, Boolean>
implements ClickNotifier<Checkbox>, Focusable<Checkbox>, HasAriaLabel,
HasClientValidation, HasValidationProperties,
HasClientValidation, HasValidationProperties, HasValidator<Boolean>,
InputField<AbstractField.ComponentValueChangeEvent<Checkbox, Boolean>, Boolean> {

private final Label labelElement;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.vaadin.flow.component.checkbox.tests.validation;

import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.BindingValidationStatus;
import com.vaadin.flow.data.binder.BindingValidationStatusHandler;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.Ignore;

import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

public class CheckboxBinderValidationTest {
private static final String BINDER_FAIL_MESSAGE = "BINDER_FAIL_MESSAGE";
private static final String BINDER_REQUIRED_MESSAGE = "REQUIRED";

private Checkbox field;

@Captor
private ArgumentCaptor<BindingValidationStatus<?>> statusCaptor;

@Mock
private BindingValidationStatusHandler statusHandlerMock;

public static class Bean {
private Boolean value;

public Boolean getValue() {
return value;
}

public void setValue(Boolean value) {
this.value = value;
}
}

@Before
public void init() {
MockitoAnnotations.openMocks(this);
field = new Checkbox();
}

@Test
public void elementWithBinderValidation_invalidValue_binderValidationFails() {
var binder = attachBinderToField();

field.setValue(true);
Mockito.verify(statusHandlerMock).statusChange(statusCaptor.capture());

Assert.assertTrue(statusCaptor.getValue().isError());
Assert.assertEquals(BINDER_FAIL_MESSAGE,
statusCaptor.getValue().getMessage().orElse(""));
}

@Test
public void setRequiredOnBinder_validate_binderValidationFails() {
var binder = attachBinderToField(true);
binder.validate();

Mockito.verify(statusHandlerMock).statusChange(statusCaptor.capture());
Assert.assertTrue(statusCaptor.getValue().isError());
Assert.assertEquals(BINDER_REQUIRED_MESSAGE,
statusCaptor.getValue().getMessage().orElse(""));
}

@Test
public void setRequiredOnComponent_validate_binderValidationPasses() {
var binder = attachBinderToField();
field.setRequiredIndicatorVisible(true);
binder.validate();

Mockito.verify(statusHandlerMock).statusChange(statusCaptor.capture());
Assert.assertFalse(statusCaptor.getValue().isError());
}

@Test
public void setRequiredOnBinder_setValidValue_binderValidationPasses() {
attachBinderToField(true);

field.setValue(true);

Mockito.verify(statusHandlerMock).statusChange(statusCaptor.capture());
Assert.assertFalse(statusCaptor.getValue().isError());
}

private Binder<Bean> attachBinderToField() {
return attachBinderToField(false);
}

private Binder<Bean> attachBinderToField(boolean isRequired) {
var binder = new Binder<>(Bean.class);
var binding = binder.forField(field)
.withValidationStatusHandler(statusHandlerMock);

if (isRequired) {
binding.asRequired(BINDER_REQUIRED_MESSAGE);
} else {
// Consider un-checked as valid
binding.withValidator(value -> Boolean.FALSE.equals(value),
BINDER_FAIL_MESSAGE);
}

binding.bind("value");

return binder;
}
}

0 comments on commit 8d81583

Please sign in to comment.