diff options
4 files changed, 291 insertions, 4 deletions
diff --git a/client/src/com/vaadin/client/ui/VCalendarPanel.java b/client/src/com/vaadin/client/ui/VCalendarPanel.java index eaa2292c69..6fc06bb153 100644 --- a/client/src/com/vaadin/client/ui/VCalendarPanel.java +++ b/client/src/com/vaadin/client/ui/VCalendarPanel.java @@ -786,6 +786,21 @@ public class VCalendarPanel extends FocusableFlexTable implements * Updates the calendar and text field with the selected dates. */ public void renderCalendar() { + renderCalendar(true); + } + + /** + * For internal use only. May be removed or replaced in the future. + * + * Updates the calendar and text field with the selected dates. + * + * @param updateDate + * The value false prevents setting the selected date of the + * calendar based on focusedDate. That can be used when only the + * resolution of the calendar is changed and no date has been + * selected. + */ + public void renderCalendar(boolean updateDate) { super.setStylePrimaryName(parent.getStylePrimaryName() + "-calendarpanel"); @@ -798,8 +813,9 @@ public class VCalendarPanel extends FocusableFlexTable implements displayedMonth = new FocusedDate(now.getYear(), now.getMonth(), 1); } - if (getResolution().getCalendarField() <= Resolution.MONTH - .getCalendarField() && focusChangeListener != null) { + if (updateDate + && getResolution().getCalendarField() <= Resolution.MONTH + .getCalendarField() && focusChangeListener != null) { focusChangeListener.focusChanged(new Date(focusedDate.getTime())); } diff --git a/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java b/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java index a349eb2993..6f059a7c16 100644 --- a/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java +++ b/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java @@ -87,15 +87,17 @@ public class PopupDateFieldConnector extends TextualDateConnector { .isShowISOWeekNumbers()); if (getWidget().calendar.getResolution() != getWidget() .getCurrentResolution()) { + boolean hasSelectedDate = false; getWidget().calendar.setResolution(getWidget() .getCurrentResolution()); if (getWidget().calendar.getDate() != null && getWidget().getCurrentDate() != null) { + hasSelectedDate = true; getWidget().calendar.setDate((Date) getWidget() .getCurrentDate().clone()); - // force re-render when changing resolution only - getWidget().calendar.renderCalendar(); } + // force re-render when changing resolution only + getWidget().calendar.renderCalendar(hasSelectedDate); } // Force re-render of calendar if locale has changed (#12153) diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolution.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolution.java new file mode 100644 index 0000000000..9dbd8fa6dc --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolution.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2014 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.tests.components.datefield; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.DateField; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.PopupDateField; + +public class DateFieldChangeResolution extends AbstractTestUI { + + public static final String DATEFIELD_ID = "datefield"; + // The ID of a button is BUTTON_BASE_ID + resolution, e.g. button-month + public static final String BUTTON_BASE_ID = "button-"; + + @Override + protected void setup(VaadinRequest request) { + final DateField dateField = new PopupDateField("Enter date"); + dateField.setResolution(Resolution.YEAR); + dateField.setId(DATEFIELD_ID); + dateField.setImmediate(true); + addComponent(dateField); + + Label l = new Label("Select resolution"); + addComponent(l); + HorizontalLayout hlayout = new HorizontalLayout(); + addComponent(hlayout); + for (final Resolution value : Resolution.values()) { + String resolutionString = value.toString().toLowerCase(); + Button b = new Button(resolutionString); + b.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + dateField.setResolution(value); + } + }); + b.setId(BUTTON_BASE_ID + resolutionString); + hlayout.addComponent(b); + } + + } + + @Override + protected String getTestDescription() { + return "The calendar should always have the correct resolution and the text field should be empty before selecting a date."; + } + + @Override + protected Integer getTicketNumber() { + return 14174; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java new file mode 100644 index 0000000000..6820410059 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java @@ -0,0 +1,197 @@ +/* + * Copyright 2000-2014 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.tests.components.datefield; + +import static com.vaadin.tests.components.datefield.DateFieldChangeResolution.BUTTON_BASE_ID; +import static com.vaadin.tests.components.datefield.DateFieldChangeResolution.DATEFIELD_ID; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; + +import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.testbench.By; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class DateFieldChangeResolutionTest extends MultiBrowserTest { + + private WebElement dateFieldButton, textField; + private WebElement resolutionSecond, resolutionMinute, resolutionHour, + resolutionDay, resolutionMonth, resolutionYear; + + @Test + public void changeResolutionBetweenYearAndMonth() throws Exception { + initialize(); + click(resolutionMonth); + checkHeaderAndBody(Resolution.MONTH, true); + click(resolutionYear); + checkHeaderAndBody(Resolution.YEAR, true); + } + + @Test + public void changeResolutionBetweenYearAndSecond() throws Exception { + initialize(); + click(resolutionSecond); + checkHeaderAndBody(Resolution.SECOND, true); + click(resolutionYear); + checkHeaderAndBody(Resolution.YEAR, true); + } + + @Test + public void changeResolutionToDayThenMonth() throws Exception { + initialize(); + checkHeaderAndBody(Resolution.YEAR, true); // check the initial state + click(resolutionDay); + checkHeaderAndBody(Resolution.DAY, true); + click(resolutionMonth); + checkHeaderAndBody(Resolution.MONTH, true); + } + + @Test + public void setDateAndChangeResolution() throws Exception { + initialize(); + // Set the date to previous month. + click(resolutionMonth); + openPopupDateField(); + click(driver.findElement(By.className("v-button-prevmonth"))); + closePopupDateField(); + assertFalse( + "The text field of the calendar should not be empty after selecting a date", + textField.getAttribute("value").isEmpty()); + // Change resolutions and check that the selected date is not lost and + // that the calendar has the correct resolution. + click(resolutionHour); + checkHeaderAndBody(Resolution.HOUR, false); + click(resolutionYear); + checkHeaderAndBody(Resolution.YEAR, false); + click(resolutionMinute); + checkHeaderAndBody(Resolution.MINUTE, false); + } + + private void initialize() { + openTestURL(); + WebElement dateField = driver.findElement(By.id(DATEFIELD_ID)); + dateFieldButton = dateField.findElement(By + .className("v-datefield-button")); + textField = dateField + .findElement(By.className("v-datefield-textfield")); + resolutionSecond = driver.findElement(By.id(BUTTON_BASE_ID + "second")); + resolutionMinute = driver.findElement(By.id(BUTTON_BASE_ID + "minute")); + resolutionHour = driver.findElement(By.id(BUTTON_BASE_ID + "hour")); + resolutionDay = driver.findElement(By.id(BUTTON_BASE_ID + "day")); + resolutionMonth = driver.findElement(By.id(BUTTON_BASE_ID + "month")); + resolutionYear = driver.findElement(By.id(BUTTON_BASE_ID + "year")); + } + + private void checkHeaderAndBody(Resolution resolution, + boolean textFieldIsEmpty) { + // Open the popup calendar, perform checks and close the popup. + openPopupDateField(); + if (resolution.getCalendarField() >= Resolution.MONTH + .getCalendarField()) { + checkMonthHeader(); + } else { + checkYearHeader(); + } + if (resolution.getCalendarField() >= Resolution.DAY.getCalendarField()) { + assertTrue( + "A calendar with the chosen resolution should have a body", + calendarHasBody()); + } else { + assertFalse( + "A calendar with the chosen resolution should not have a body", + calendarHasBody()); + } + if (textFieldIsEmpty) { + assertTrue("The text field of the calendar should be empty", + textField.getAttribute("value").isEmpty()); + } else { + assertFalse("The text field of the calendar should not be empty", + textField.getAttribute("value").isEmpty()); + } + closePopupDateField(); + } + + private void checkMonthHeader() { + checkHeaderForYear(); + checkHeaderForMonth(true); + } + + private void checkYearHeader() { + checkHeaderForYear(); + checkHeaderForMonth(false); + } + + private boolean calendarHasBody() { + return isElementPresent(By.className("v-datefield-calendarpanel-body")); + } + + private void checkHeaderForMonth(boolean buttonsExpected) { + // If buttonsExpected is true, check that there are buttons for changing + // the month. Otherwise check that there are no such buttons. + if (buttonsExpected) { + assertTrue( + "The calendar should have a button for switching to the previous month", + isElementPresent(By + .cssSelector(".v-datefield-calendarpanel-header .v-datefield-calendarpanel-prevmonth .v-button-prevmonth"))); + assertTrue( + "The calendar should have a button for switching to the next month", + isElementPresent(By + .cssSelector(".v-datefield-calendarpanel-header .v-datefield-calendarpanel-nextmonth .v-button-nextmonth"))); + } else { + assertFalse( + "The calendar should not have a button for switching to the previous month", + isElementPresent(By + .cssSelector(".v-datefield-calendarpanel-header .v-datefield-calendarpanel-prevmonth .v-button-prevmonth"))); + assertFalse( + "The calendar should not have a button for switching to the next month", + isElementPresent(By + .cssSelector(".v-datefield-calendarpanel-header .v-datefield-calendarpanel-nextmonth .v-button-nextmonth"))); + } + } + + private void checkHeaderForYear() { + assertTrue( + "The calendar should have a button for switching to the previous year", + isElementPresent(By + .cssSelector(".v-datefield-calendarpanel-header .v-datefield-calendarpanel-prevyear .v-button-prevyear"))); + assertTrue( + "The calendar header should show the selected year", + isElementPresent(By + .cssSelector(".v-datefield-calendarpanel-header .v-datefield-calendarpanel-month"))); + assertTrue( + "The calendar should have a button for switching to the next year", + isElementPresent(By + .cssSelector(".v-datefield-calendarpanel-header .v-datefield-calendarpanel-nextyear .v-button-nextyear"))); + + } + + private void click(WebElement element) { + testBenchElement(element).click(5, 5); + } + + private void openPopupDateField() { + click(dateFieldButton); + } + + private void closePopupDateField() { + WebElement element = driver.findElement(By + .cssSelector(".v-datefield-calendarpanel")); + element.sendKeys(Keys.ESCAPE); + } +} |