Browse Source

Set DateField value only if it passes range check (#11887)

Fixes #11108
tags/8.11.0.alpha1
Tatu Lund 4 years ago
parent
commit
a486f64809
No account linked to committer's email address

+ 34
- 17
server/src/main/java/com/vaadin/ui/AbstractDateField.java View File

* validate. If {@code startDate} is set to {@code null}, any value before * validate. If {@code startDate} is set to {@code null}, any value before
* {@code endDate} will be accepted by the range * {@code endDate} will be accepted by the range
* <p> * <p>
* Note: Negative, i.e. BC dates are not supported
* Note: Negative, i.e. BC dates are not supported.
* <p>
* Note: It's usually recommended to use only one of the following at the same
* time: Range validator with Binder or DateField's setRangeStart check.
* *
* @param startDate * @param startDate
* - the allowed range's start date * - the allowed range's start date
* date (taking the resolution into account), the component will not * date (taking the resolution into account), the component will not
* validate. If {@code endDate} is set to {@code null}, any value after * validate. If {@code endDate} is set to {@code null}, any value after
* {@code startDate} will be accepted by the range. * {@code startDate} will be accepted by the range.
* <p>
* Note: It's usually recommended to use only one of the following at the same
* time: Range validator with Binder or DateField's setRangeEnd check.
* *
* @param endDate * @param endDate
* the allowed range's end date (inclusive, based on the current * the allowed range's end date (inclusive, based on the current
* *
* @param value * @param value
* the new value, may be {@code null} * the new value, may be {@code null}
* @throws IllegalArgumentException
* if the value is not within range bounds
*/ */
@Override @Override
public void setValue(T value) { public void setValue(T value) {
currentErrorMessage = null;
/*
* First handle special case when the client side component have a date
* string but value is null (e.g. unparsable date string typed in by the
* user). No value changes should happen, but we need to do some
* internal housekeeping.
*/
if (value == null && !getState(false).parsable) {
RangeValidator<T> validator = getRangeValidator();
ValidationResult result = validator.apply(value,
new ValueContext(this, this));

if (result.isError()) {
throw new IllegalArgumentException(
"value is not within acceptable range");
} else {
currentErrorMessage = null;
/* /*
* Side-effects of doSetValue clears possible previous strings and
* flags about invalid input.
* First handle special case when the client side component has a date
* string but value is null (e.g. unparsable date string typed in by the
* user). No value changes should happen, but we need to do some
* internal housekeeping.
*/ */
doSetValue(null);

markAsDirty();
return;
if (value == null && !getState(false).parsable) {
/*
* Side-effects of doSetValue clears possible previous strings and
* flags about invalid input.
*/
doSetValue(null);

markAsDirty();
return;
}
super.setValue(value);
} }
super.setValue(value);
} }


/** /**
@Override @Override
protected void doSetValue(T value) { protected void doSetValue(T value) {


this.value = value;
// Also set the internal dateString // Also set the internal dateString
this.value = value;
if (value == null) { if (value == null) {
value = getEmptyValue(); value = getEmptyValue();
} }

+ 11
- 2
server/src/test/java/com/vaadin/ui/DateFieldTestCase.java View File



import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.Rule;
import org.junit.rules.ExpectedException;


public class DateFieldTestCase { public class DateFieldTestCase {


private AbstractLocalDateField dateField; private AbstractLocalDateField dateField;
private LocalDate date; private LocalDate date;


@Rule
public transient ExpectedException exceptionRule = ExpectedException.none();

@Before @Before
public void setup() { public void setup() {
dateField = new AbstractLocalDateField() { dateField = new AbstractLocalDateField() {


@Test @Test
public void belowRangeStartIsNotAcceptedAsValue() { public void belowRangeStartIsNotAcceptedAsValue() {
LocalDate currentDate = dateField.getValue();
dateField.setRangeStart(date); dateField.setRangeStart(date);
exceptionRule.expect(IllegalArgumentException.class);
dateField.setValue(date.minusDays(1)); dateField.setValue(date.minusDays(1));
assertNotNull(dateField.getComponentError());
assertThat(dateField.getValue(), is(currentDate));
} }


@Test @Test


@Test @Test
public void aboveRangeEndIsNotAcceptedAsValue() { public void aboveRangeEndIsNotAcceptedAsValue() {
LocalDate currentDate = dateField.getValue();
dateField.setRangeEnd(date); dateField.setRangeEnd(date);
exceptionRule.expect(IllegalArgumentException.class);
dateField.setValue(date.plusDays(1)); dateField.setValue(date.plusDays(1));
assertNotNull(dateField.getComponentError());
assertThat(dateField.getValue(), is(currentDate));
} }
} }

+ 2
- 0
uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldBinderCrossValidationTest.java View File

fromFieldText.sendKeys("2019/01/01", Keys.ENTER); fromFieldText.sendKeys("2019/01/01", Keys.ENTER);
toFieldText.sendKeys("2018/02/02", Keys.ENTER); toFieldText.sendKeys("2018/02/02", Keys.ENTER);


sleep(200);

assertEquals("Error message should contain the information", assertEquals("Error message should contain the information",
EXPECTED_ERROR, label.getText()); EXPECTED_ERROR, label.getText());



+ 4
- 1
uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldFaultyInputNotValidTest.java View File



import org.junit.Test; import org.junit.Test;
import org.openqa.selenium.By; import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.WebElement;


import com.vaadin.testbench.elements.ButtonElement; import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.testbench.elements.DateFieldElement; import com.vaadin.testbench.elements.DateFieldElement;
public void testDateOutOfRange() { public void testDateOutOfRange() {
openTestURL(); openTestURL();
DateFieldElement dateField = $(DateFieldElement.class).first(); DateFieldElement dateField = $(DateFieldElement.class).first();
WebElement dateFieldText = dateField.findElement(By.tagName("input"));
dateField.setDate(LocalDate.now()); dateField.setDate(LocalDate.now());


$(ButtonElement.class).first().click(); $(ButtonElement.class).first().click();
$(NotificationElement.class).first().getText()); $(NotificationElement.class).first().getText());
$(NotificationElement.class).first().close(); $(NotificationElement.class).first().close();


dateField.setDate(LocalDate.now().minusDays(7));
dateFieldText.sendKeys(LocalDate.now().minusDays(7).toString(), Keys.ENTER);


$(ButtonElement.class).first().click(); $(ButtonElement.class).first().click();
assertEquals("Last week should not be ok", "Fail", assertEquals("Last week should not be ok", "Fail",

Loading…
Cancel
Save