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

@@ -297,7 +297,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
* validate. If {@code startDate} is set to {@code null}, any value before
* {@code endDate} will be accepted by the range
* <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
* - the allowed range's start date
@@ -359,6 +362,9 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
* date (taking the resolution into account), the component will not
* validate. If {@code endDate} is set to {@code null}, any value after
* {@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
* the allowed range's end date (inclusive, based on the current
@@ -618,27 +624,38 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
*
* @param value
* the new value, may be {@code null}
* @throws IllegalArgumentException
* if the value is not within range bounds
*/
@Override
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);
}

/**
@@ -785,8 +802,8 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
@Override
protected void doSetValue(T value) {

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

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

@@ -10,12 +10,17 @@ import java.time.LocalDate;

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

public class DateFieldTestCase {

private AbstractLocalDateField dateField;
private LocalDate date;

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

@Before
public void setup() {
dateField = new AbstractLocalDateField() {
@@ -39,9 +44,11 @@ public class DateFieldTestCase {

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

@Test
@@ -60,8 +67,10 @@ public class DateFieldTestCase {

@Test
public void aboveRangeEndIsNotAcceptedAsValue() {
LocalDate currentDate = dateField.getValue();
dateField.setRangeEnd(date);
exceptionRule.expect(IllegalArgumentException.class);
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

@@ -30,6 +30,8 @@ public class DateFieldBinderCrossValidationTest extends SingleBrowserTest {
fromFieldText.sendKeys("2019/01/01", Keys.ENTER);
toFieldText.sendKeys("2018/02/02", Keys.ENTER);

sleep(200);

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


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

@@ -6,7 +6,9 @@ import java.time.LocalDate;

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

import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.testbench.elements.DateFieldElement;
@@ -46,6 +48,7 @@ public class DateFieldFaultyInputNotValidTest extends SingleBrowserTest {
public void testDateOutOfRange() {
openTestURL();
DateFieldElement dateField = $(DateFieldElement.class).first();
WebElement dateFieldText = dateField.findElement(By.tagName("input"));
dateField.setDate(LocalDate.now());

$(ButtonElement.class).first().click();
@@ -53,7 +56,7 @@ public class DateFieldFaultyInputNotValidTest extends SingleBrowserTest {
$(NotificationElement.class).first().getText());
$(NotificationElement.class).first().close();

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

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

Loading…
Cancel
Save