Fixes #11108tags/8.11.0.alpha1
* 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(); | ||||
} | } |
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)); | |||||
} | } | ||||
} | } |
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()); | ||||
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", |