/* * $Id$ * * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jdesktop.swingx; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.GraphicsEnvironment; import java.awt.event.ActionListener; import java.lang.reflect.InvocationTargetException; import java.text.DateFormat; import java.text.Format; import java.text.MessageFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import java.util.logging.Logger; import javax.swing.Action; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFormattedTextField; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.UIResource; import javax.swing.text.DateFormatter; import javax.swing.text.DefaultFormatterFactory; import org.jdesktop.swingx.calendar.CalendarUtils; import org.jdesktop.swingx.calendar.DatePickerFormatter; import org.jdesktop.swingx.calendar.DateSelectionModel; import org.jdesktop.swingx.calendar.DefaultDateSelectionModel; import org.jdesktop.swingx.calendar.SingleDaySelectionModel; import org.jdesktop.swingx.plaf.UIManagerExt; import org.jdesktop.swingx.plaf.basic.BasicDatePickerUI.EditorCancelAction; import org.jdesktop.swingx.test.XTestUtils; import org.jdesktop.test.ActionReport; import org.jdesktop.test.PopupMenuReport; import org.jdesktop.test.PropertyChangeReport; import org.jdesktop.test.TestUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Unit tests for JXDatePicker. */ @RunWith(JUnit4.class) public class JXDatePickerTest extends InteractiveTestCase { private static final Logger LOG = Logger.getLogger(JXDatePickerTest.class .getName()); private Calendar calendar; /** * Issue #1393-swingx: JXDatePicker children must show parent popup if inherits true * * Here: sanity test of JComboBox for comparison */ @Test public void testComboInheritsComponentPopup() { JComboBox box = new JComboBox(new Object[] {"some", "other"}); box.setInheritsPopupMenu(true); box.setEditable(true); JPanel parent = new JPanel(); JPopupMenu popup = new JPopupMenu(); popup.add("dummy"); parent.setComponentPopupMenu(popup); parent.add(box); // sanity: combobox assertInheritedPopup(box, popup); } /** * Issue #1393-swingx: JXDatePicker children must show parent popup if inherits true * * Here: sanity test of JComboBox for comparison */ @Test public void testDatePickerInheritsComponentPopup() { JXDatePicker box = new JXDatePicker(); box.setInheritsPopupMenu(true); JPanel parent = new JPanel(); JPopupMenu popup = new JPopupMenu(); popup.add("dummy"); parent.setComponentPopupMenu(popup); parent.add(box); // sanity: combobox assertInheritedPopup(box, popup); } private void assertInheritedPopup(JComponent box, JPopupMenu popup) { assertSame("inherited popup expected on " + box.getClass(), popup, box.getComponentPopupMenu()); for (int i = 0; i < box.getComponentCount(); i++) { if (box.getComponent(i) instanceof JComponent) assertSame("inherited popup expected on " + box.getComponent(i).getClass(), popup, ((JComponent) box.getComponent(i)).getComponentPopupMenu()); } } /** * Issue #1301-swingx: Picker must be source of popupMenuEvent. * * Tests event source on notification. * * @throws InvocationTargetException * @throws InterruptedException */ @Test public void testPopupMenuListenerNotificationPickerIsSourceOnShowing() throws InterruptedException, InvocationTargetException { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } final JXDatePicker picker = new JXDatePicker(); final JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.pack(); frame.setVisible(true); final PopupMenuReport report = new PopupMenuReport(); picker.addPopupMenuListener(report); Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertEquals(1, report.getVisibleEventCount()); assertEquals(picker, report.getLastEvent().getSource()); frame.dispose(); } }); } /** * Issue #1301-swingx: Picker must be source of popupMenuEvent. * * Tests event source on notification. * * @throws InvocationTargetException * @throws InterruptedException */ @Test public void testPopupMenuListenerNotificationPickerIsSourceOnHiding() throws InterruptedException, InvocationTargetException { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } final JXDatePicker picker = new JXDatePicker(); final JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.pack(); frame.setVisible(true); final Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); final PopupMenuReport report = new PopupMenuReport(); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { picker.addPopupMenuListener(report); togglePopup.actionPerformed(null); } }); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertEquals(1, report.getInvisibleEventCount()); assertEquals(picker, report.getLastEvent().getSource()); frame.dispose(); } }); } /** * Issue #1171-swingx: support popupMenuListeners. * * Tests notification on showing. * @throws InvocationTargetException * @throws InterruptedException */ @Test public void testPopupMenuListenerNotificationVisible() throws InterruptedException, InvocationTargetException { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } final JXDatePicker picker = new JXDatePicker(); final JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.pack(); frame.setVisible(true); final PopupMenuReport report = new PopupMenuReport(); picker.addPopupMenuListener(report); Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertEquals(1, report.getEventCount()); assertEquals(1, report.getVisibleEventCount()); frame.dispose(); } }); } /** * Issue #1171-swingx: support popupMenuListeners. * Issue #1172-swingx: missing cancel notification. * * Tests notification on cancel. * * @throws InvocationTargetException * @throws InterruptedException */ @Test public void testPopupMenuListenerNotificationCancel() throws InterruptedException, InvocationTargetException { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } final JXDatePicker picker = new JXDatePicker(); final JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.pack(); frame.setVisible(true); final Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); final PopupMenuReport report = new PopupMenuReport(); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { picker.addPopupMenuListener(report); picker.getMonthView().cancelSelection(); } }); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertEquals(2, report.getEventCount()); assertEquals(1, report.getInvisibleEventCount()); assertEquals(1, report.getCanceledEventCount()); frame.dispose(); } }); } /** * Issue #1171-swingx: support popupMenuListeners. * * Tests notification on showing. * @throws InvocationTargetException * @throws InterruptedException */ @Test public void testPopupMenuListenerNotificationInvisible() throws InterruptedException, InvocationTargetException { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } final JXDatePicker picker = new JXDatePicker(); final JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.pack(); frame.setVisible(true); final Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); final PopupMenuReport report = new PopupMenuReport(); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { picker.addPopupMenuListener(report); togglePopup.actionPerformed(null); } }); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertEquals(1, report.getEventCount()); assertEquals(1, report.getInvisibleEventCount()); frame.dispose(); } }); } /** * Issue #1171-swingx: support popupMenuListeners. * * Tests add/remove. */ @Test public void testPopupMenuListenerManagement() { JXDatePicker picker = new JXDatePicker(); assertNotNull(picker.getPopupMenuListeners()); int count = picker.getPopupMenuListeners().length; PopupMenuReport report = new PopupMenuReport(); picker.addPopupMenuListener(report); assertEquals(count + 1, picker.getPopupMenuListeners().length); assertTrue(Arrays.asList(picker.getPopupMenuListeners()).contains(report)); picker.removePopupMenuListener(report); assertEquals(count, picker.getPopupMenuListeners().length); assertFalse(Arrays.asList(picker.getPopupMenuListeners()).contains(report)); } /** * Issue #1144-swingx: JXDatePicker must accept custom formatter. * Pathological .. but anyway: formatter may be null. * Issue manifests in throwing NPE. */ @Test public void testCustomFormatterNull() { JXDatePicker picker = new JXDatePicker(); DefaultFormatterFactory factory = new DefaultFormatterFactory(); assertEquals("sanity (null formatter): ", null, factory.getFormatter(picker.getEditor())); picker.getEditor().setFormatterFactory(factory); picker.updateUI(); } /** * Issue #1144-swingx: JXDatePicker must accept custom formatter. * Use core DateFormatter - issue manifests in throwing classcastEx */ @Test public void testCustomFormatterCore() { JXDatePicker picker = new JXDatePicker(); DefaultFormatterFactory factory = new DefaultFormatterFactory(new DateFormatter()); picker.getEditor().setFormatterFactory(factory); picker.updateUI(); } /** * Issue #910-swingx: home commit must be disabled if picker not editable. * */ @Test public void testNotEditableNullHomeNavigate() { JXDatePicker picker = new JXDatePicker(); picker.getActionMap().remove(JXDatePicker.HOME_NAVIGATE_KEY); picker.setEditable(!picker.isEditable()); } /** * Issue #910-swingx: home commit must be disabled if picker not editable. * */ @Test public void testNotEditableDisabledHomeNavigate() { JXDatePicker picker = new JXDatePicker(); Action delegate = picker.getActionMap().get(JXDatePicker.HOME_NAVIGATE_KEY); assertEquals(picker.isEditable(), delegate.isEnabled()); picker.setEditable(!picker.isEditable()); assertEquals(picker.isEditable(), delegate.isEnabled()); } /** * Issue #910-swingx: home commit must be disabled if picker not editable. * */ @Test public void testNotEditableNullHomeCommit() { JXDatePicker picker = new JXDatePicker(); picker.getActionMap().remove(JXDatePicker.HOME_COMMIT_KEY); picker.setEditable(!picker.isEditable()); } /** * Issue #910-swingx: home commit must be disabled if picker not editable. * */ @Test public void testNotEditableDisabledHomeCommit() { JXDatePicker picker = new JXDatePicker(); Action delegate = picker.getActionMap().get(JXDatePicker.HOME_COMMIT_KEY); assertEquals(picker.isEditable(), delegate.isEnabled()); picker.setEditable(!picker.isEditable()); assertEquals(picker.isEditable(), delegate.isEnabled()); } /** * Issue #1196-swingx: JXDatePicker editor must be disabled if picker disabled. * Enabled must be kept in synch on updateUI. */ @Test public void testEnabledKeptOnUpdateUI() { JXDatePicker picker = new JXDatePicker(); picker.setEnabled(false); assertFalse("sanity: picker disabled", picker.isEnabled()); assertEquals("editor enabled must follow picker enabled", picker.isEnabled(), picker.getEditor().isEnabled()); picker.updateUI(); assertFalse("sanity: picker disabled", picker.isEnabled()); for (int i = 0; i < picker.getComponentCount(); i++) { assertEquals("child enabled must follow picker enabled", picker.isEnabled(), picker.getComponent(i).isEnabled()); } } /** * Issue #1196-swingx: JXDatePicker editor must be disabled if picker disabled. * Enabled must be kept in synch on setEditor. */ @Test public void testEnabledKeptOnSetEditor() { JXDatePicker picker = new JXDatePicker(); picker.setEnabled(false); picker.setEditor(new JFormattedTextField()); assertFalse("sanity: picker disabled", picker.isEnabled()); assertEquals("editor enabled must follow picker enabled", picker.isEnabled(), picker.getEditor().isEnabled()); } /** * Issue #1196-swingx: JXDatePicker editor must be disabled if picker disabled. * Editable must be kept in synch on updateUI. */ @Test public void testEditableKeptOnUpdateUI() { JXDatePicker picker = new JXDatePicker(); picker.setEditable(false); assertFalse("sanity: picker disabled", picker.isEditable()); assertEquals("editor enabled must follow picker enabled", picker.isEditable(), picker.getEditor().isEditable()); picker.updateUI(); assertFalse("sanity: picker disabled", picker.isEditable()); assertEquals("editor enabled must follow picker enabled", picker.isEditable(), picker.getEditor().isEditable()); } /** * Issue #1196-swingx: JXDatePicker editor must be disabled if picker disabled. * Editable must be kept in synch on setEditor. */ @Test public void testEditableSynchedOnSetEditor() { JXDatePicker picker = new JXDatePicker(); picker.setEditable(false); picker.setEditor(new JFormattedTextField()); assertFalse("sanity: picker disabled", picker.isEditable()); assertEquals("editor enabled must follow picker enabled", picker.isEditable(), picker.getEditor().isEditable()); } /** * Issue #764-swingx: JXDatePicker sizing * * editor must respect columns. */ @Test public void testDatePickerColumns50() { JXDatePicker picker = new JXDatePicker(); picker.getEditor().setColumns(50); JXDatePicker other = new JXDatePicker(new Date()); other.getEditor().setColumns(50); assertEquals(other.getEditor().getPreferredSize(), picker.getEditor().getPreferredSize()); } /** * Issue #764-swingx: JXDatePicker sizing * * editor must respect columns. */ @Test public void testDatePickerColumns5() { JXDatePicker picker = new JXDatePicker(); picker.getEditor().setColumns(5); JXDatePicker other = new JXDatePicker(new Date()); other.getEditor().setColumns(5); assertEquals(other.getEditor().getPreferredSize(), picker.getEditor().getPreferredSize()); } /** * Issue #667-swingx: don't install the datepicker border for gtk. * * Here we are testing that the BasicPickerUI doesn't touch the * editors border if it finds a null. * */ @Test public void testPickerBorder() { // force loading of addon new JXDatePicker(); Border pickerBorder = UIManager.getBorder("JXDatePicker.border"); if (pickerBorder == null) { LOG.info("cant run test - no pickerborder"); return; } try { UIManager.put("JXDatePicker.border", "none"); assertNull(UIManager.getBorder("JXDatePicker.border")); JXDatePicker picker = new JXDatePicker(); JTextField field = new JFormattedTextField(); assertEquals(field.getBorder(), picker.getEditor().getBorder()); } finally { // restore LAF border UIManager.put("JXDatePicker.border", null); assertEquals(pickerBorder, UIManager.getBorder("JXDatePicker.border")); } } /** * Issue #724-swingx: picker must notify about timezone changes. * Here: change the timezone on the monthView - can't guarantee the notification. * At least not without hacks... */ @Test public void testTimeZoneChangeNotificationChangeOnMonthView() { JXDatePicker picker = new JXDatePicker(); TimeZone timeZone = picker.getTimeZone(); TimeZone alternative = getSafeAlternativeTimeZone(timeZone); PropertyChangeReport report = new PropertyChangeReport(); picker.addPropertyChangeListener(report); picker.getMonthView().setTimeZone(alternative); TestUtils.assertPropertyChangeEvent(report, "timeZone", timeZone, alternative, false); } /** * Issue #724-swingx: picker must notify about timezone changes. * Here: change the timezon on the picker - can guarantee the notification. */ @Test public void testTimeZoneChangeNotification() { JXDatePicker picker = new JXDatePicker(); TimeZone timeZone = picker.getTimeZone(); TimeZone alternative = getSafeAlternativeTimeZone(timeZone); PropertyChangeReport report = new PropertyChangeReport(); picker.addPropertyChangeListener(report); picker.setTimeZone(alternative); TestUtils.assertPropertyChangeEvent(report, "timeZone", timeZone, alternative, false); } /** * Issue #724-swingx: picker must notify about timezone changes. * Here: setMonthView must update the picker's timezone if different and * fire a notification. */ @Test public void testTimeZoneSetMonthView() { JXDatePicker picker = new JXDatePicker(); TimeZone timeZone = picker.getTimeZone(); TimeZone alternative = getSafeAlternativeTimeZone(timeZone); // prepare a new monthView with different TimeZone JXMonthView monthView = new JXMonthView(); monthView.setTimeZone(alternative); PropertyChangeReport report = new PropertyChangeReport(); picker.addPropertyChangeListener(report); picker.setMonthView(monthView); TestUtils.assertPropertyChangeEvent(report, "timeZone", timeZone, alternative, false); report.clear(); TimeZone another = getSafeAlternativeTimeZone(alternative); monthView.setTimeZone(another); TestUtils.assertPropertyChangeEvent(report, "timeZone", alternative, another, false); } /** * Issue #568-swingx: picker must respect selection model (as of time fields). * * Behaviour defined by selection model of monthView. While the default * (DaySelectionModel) normalizes the dates to the start of the day in the * model's calendar coordinates, a SingleDaySelectionModel keeps the date as-is. * For now, need to explicitly set. */ @Test public void testSetDateKeepsTime() { JXDatePicker picker = new JXDatePicker(); DateSelectionModel selectionModel = new SingleDaySelectionModel(); picker.getMonthView().setSelectionModel(selectionModel); Date date = new Date(); selectionModel.setSelectionInterval(date, date); Date first = selectionModel.getFirstSelectionDate(); assertEquals("formats diff: " + (date.getTime() - first.getTime()) , date, first); } /** * Issue #??-swingx: JXDatePicker must keep monthView's firstDisplayedDate * in synch with selection/today. * Issue #705-swingx: JXMonthView must not scroll in layoutContainer. * * The implication is that client code (such as JXDatePicker/UI) is * responsible to do the scrolling. */ @Test public void testVisibleMonthContainsSelectionOpenSet() { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } calendar.set(2008, Calendar.JULY, 15); JXDatePicker picker = new JXDatePicker(); picker.setDate(calendar.getTime()); JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.pack(); frame.setVisible(true); Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); CalendarUtils.startOfMonth(calendar); assertEquals(calendar.getTime(), picker.getMonthView().getFirstDisplayedDay()); frame.dispose(); } /** * Issue #??-swingx: JXDatePicker must keep monthView's firstDisplayedDate * in synch with selection/today. * Issue #705-swingx: JXMonthView must not scroll in layoutContainer. * * The implication is that client code (such as JXDatePicker/UI) is * responsible to do the scrolling. */ @Test public void testVisibleMonthContainsSelectionOpenInitial() { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } calendar.set(2008, Calendar.JULY, 15); JXDatePicker picker = new JXDatePicker(calendar.getTime()); JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.setVisible(true); Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); CalendarUtils.startOfMonth(calendar); assertEquals(calendar.getTime(), picker.getMonthView().getFirstDisplayedDay()); frame.dispose(); } /** * Issue #??-swingx: JXDatePicker must keep monthView's firstDisplayedDate * in synch with selection/today. * Issue #705-swingx: JXMonthView must not scroll in layoutContainer. * * The implication is that client code (such as JXDatePicker/UI) is * responsible to do the scrolling. */ @Test public void testVisibleMonthContainsSelectionIinitial() { calendar.set(2008, Calendar.JULY, 15); JXDatePicker picker = new JXDatePicker(calendar.getTime()); CalendarUtils.startOfMonth(calendar); assertEquals(calendar.getTime(), picker.getMonthView().getFirstDisplayedDay()); } /** * Issue #??-swingx: JXDatePicker must keep monthView's firstDisplayedDate * in synch with selection/today. * Issue #705-swingx: JXMonthView must not scroll in layoutContainer. * * The implication is that client code (such as JXDatePicker/UI) is * responsible to do the scrolling. */ @Test public void testVisibleMonthContainsSelectionSet() { JXDatePicker picker = new JXDatePicker(); calendar.set(2008, Calendar.JULY, 15); picker.setDate(calendar.getTime()); CalendarUtils.startOfMonth(calendar); assertEquals(calendar.getTime(), picker.getMonthView().getFirstDisplayedDay()); } /** * Issue #693-swingx: format of custom locale. * Here: test constructor with locale parameter. */ @Test public void testCustomLocaleConstructor() { Locale german = Locale.GERMAN; JXDatePicker picker = new JXDatePicker(german); SimpleDateFormat format = (SimpleDateFormat) picker.getFormats()[0]; String pattern = UIManagerExt.getString("JXDatePicker.longFormat", german); assertEquals(pattern , format.toPattern()); } /** * Issue #693-swingx: format of custom locale. * Here: test setLocale. */ @Test public void testCustomLocaleSet() { Locale german = Locale.GERMAN; JXDatePicker picker = new JXDatePicker(); picker.setLocale(german); SimpleDateFormat format = (SimpleDateFormat) picker.getFormats()[0]; String pattern = UIManagerExt.getString("JXDatePicker.longFormat", german); assertEquals(pattern , format.toPattern()); } /** * Issue #690-swingx: custom dateformats lost on switching LF. * * Here: default formats re-set. */ @Test public void testDefaultFormats() { JXDatePicker picker = new JXDatePicker(); DateFormat[] formats = picker.getFormats(); assertEquals(formats.length, picker.getFormats().length); picker.updateUI(); assertNotSame(formats[0], picker.getFormats()[0]); } /** * Issue #690-swingx: custom dateformats lost on switching LF. * * Sanity test: custom format set as expected. */ @Test public void testCustomFormatsSet() { JXDatePicker picker = new JXDatePicker(); DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM,Locale.UK); picker.setFormats(format); DateFormat[] formats = picker.getFormats(); // sanity assertEquals(1, formats.length); assertSame(format, formats[0]); } /** * Issue #690-swingx: custom dateformats lost on switching LF. * * Here: test that custom format is unchanged after updateUI */ @Test public void testCustomFormatsKept() { JXDatePicker picker = new JXDatePicker(); DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM,Locale.UK); picker.setFormats(format); picker.updateUI(); DateFormat[] formats = picker.getFormats(); assertEquals(1, formats.length); assertSame(format, formats[0]); } /** * Issue #542-swingx: NPE in init if linkFormat not set. * * After plaf cleanup no longer as virulent as earlier: with * addResourceBundle, there's always at least the fall-back value in the * bundle, so as long as the bundle is loaded at all, we have a not-null * value (and no way to remove which is okay). * */ @Test public void testLinkFormatStringNull() { // force loading new JXDatePicker(); String key = "JXDatePicker.linkFormat"; String oldLinkFormat = UIManagerExt.getString(key); // sanity: the addon was loaded assertNotNull(oldLinkFormat); UIManager.put(key, null); assertEquals("no null overwrite", oldLinkFormat, UIManagerExt.getString(key)); UIManager.getLookAndFeelDefaults().remove(key); assertEquals("no remove", oldLinkFormat, UIManagerExt.getString(key)); new JXDatePicker(); } /** * Issue #584-swingx: need to clarify null handling. * * Forum report: NPE under certain initial conditions. * */ @Test public void testPickerFormatSetFormats() { JXDatePicker picker = new JXDatePicker(); picker.setFormats((DateFormat[])null); } /** * Issue #584-swingx: need to clarify null handling. * * Forum report: NPE under certain initial conditions. * */ @Test public void testPickerFormatSetFormatsNullElements() { JXDatePicker picker = new JXDatePicker(); try { picker.setFormats(new DateFormat[] { null}); fail("must not accept null elements in format array"); } catch (NullPointerException e) { // doc'ed behaviour } } /** * Issue #584-swingx: need to clarify null handling. * * Forum report: NPE under certain initial conditions. * */ @Test public void testPickerFormatSetFormatStrings() { JXDatePicker picker = new JXDatePicker(); picker.setFormats((String[])null); } /** * Issue #584-swingx: need to clarify null handling. * * Forum report: NPE under certain initial conditions. * */ @Test public void testPickerFormatSetFormatStringsNullElements() { JXDatePicker picker = new JXDatePicker(); try { picker.setFormats(new String[] {null}); fail("must not accept null elements in format array"); } catch (NullPointerException e) { // doc'ed behaviour } } /** * Issue #584-swingx: need to clarify null handling. * * Forum report: NPE under certain initial conditions. * This produced exactly the stacktrace as reported. * */ @Test public void testPickerFormatsNotNull() { JXDatePicker picker = new JXDatePicker(); // trick the picker - no formats picker.getEditor().setFormatterFactory(new DefaultFormatterFactory( new DatePickerFormatter((DateFormat[]) null))); assertNotNull("picker format array must not be null", picker.getFormats()); } /** * Issue #584-swingx: need to clarify null handling. * * */ @Test public void testPickerFormatsNotNullUnknownFormatter() { JXDatePicker picker = new JXDatePicker(); // trick the picker - no formats picker.getEditor().setFormatterFactory(new DefaultFormatterFactory()); assertNotNull("picker format array must not be null", picker.getFormats()); } /** * Issue #565-swingx: popup not closed when focus moved to Combo * Issue #573-swingx: datePicker editor not focused on F2 (in table) * * testing internals: need focus listener add/remove * */ @Test public void testFocusListenerOnPicker() { JXDatePicker picker = new JXDatePicker(); assertEquals(1, picker.getFocusListeners().length); picker.getUI().uninstallUI(picker); assertEquals(0, picker.getFocusListeners().length); } /** * Issue #565-swingx: popup not closed when focus moved to Combo * Issue #573-swingx: datePicker editor not focused on F2 (in table) * * testing internals: need focus listener add/remove * */ @Test public void testFocusListenerOnEditor() { JFormattedTextField field = new JFormattedTextField(new DatePickerFormatter()); int listenerCount = field.getFocusListeners().length; JXDatePicker picker = new JXDatePicker(); assertEquals(listenerCount + 1, picker.getEditor().getFocusListeners().length); picker.getUI().uninstallUI(picker); assertEquals(listenerCount, picker.getEditor().getFocusListeners().length); } /** * tests LinkPanel set to null after showing. * Was: NPE. */ @Test public void testLinkPanelSetNull() { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } JXDatePicker picker = new JXDatePicker(); JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.setVisible(true); Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); picker.setLinkPanel(null); frame.dispose(); } /** * tests initial null linkPanel. * */ @Test public void testLinkPanelInitalNull() { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } JXDatePicker picker = new JXDatePicker(); picker.setLinkPanel(null); JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.setVisible(true); Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); frame.dispose(); } /** * Test install/uninstall of LinkPanel when popup is showing. * - removed/added from parent * - bindings initially installed/uninstalled/re-installed */ @Test public void testLinkPanelRemovedAdded() { if (GraphicsEnvironment.isHeadless()) { LOG.fine("cannot run testLinkPanelNull - headless"); return; } JXDatePicker picker = new JXDatePicker(); JXFrame frame = new JXFrame("showing", false); frame.add(picker); frame.setVisible(true); // show the popup ... PENDING: need api on picker. Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); togglePopup.actionPerformed(null); JPanel linkPanel = picker.getLinkPanel(); // assert the bindings are installed assertLinkPanelBindings(linkPanel, true); Container oldParent = linkPanel.getParent(); // sanity assertNotNull(oldParent); // remove picker.setLinkPanel(null); // assert it is removed assertNull("linkPanel must be removed", linkPanel.getParent()); // assert bindings removed assertLinkPanelBindings(linkPanel, false); // set again picker.setLinkPanel(linkPanel); // assert the bindings are installed again assertLinkPanelBindings(linkPanel, true); assertSame("linkPanel must be added to same parent", oldParent, linkPanel.getParent()); frame.dispose(); } /** * Tests that the linkPanel bindings and actions * are removed (no popup) * */ @Test public void testLinkPanelBindingUninstalled() { JXDatePicker picker = new JXDatePicker(); JComponent linkPanel = picker.getLinkPanel(); picker.setLinkPanel(null); assertLinkPanelBindings(linkPanel, false); } /** * Tests that the linkPanel has actions and keybindings * for homeCommit/-Cancel (initially, no popup) * */ @Test public void testLinkPanelAction() { JXDatePicker picker = new JXDatePicker(); JComponent linkPanel = picker.getLinkPanel(); assertLinkPanelBindings(linkPanel, true); } /** * @param linkPanel */ private void assertLinkPanelBindings(JComponent linkPanel, boolean bound) { if (bound) { assertNotNull("home commit action must be registered", linkPanel.getActionMap().get(JXDatePicker.HOME_COMMIT_KEY)); assertNotNull("home navigate action must be registered", linkPanel.getActionMap().get(JXDatePicker.HOME_NAVIGATE_KEY)); } else { assertNull("home commit action must not be registered", linkPanel.getActionMap().get(JXDatePicker.HOME_COMMIT_KEY)); assertNull("home navigate action must not be registered", linkPanel.getActionMap().get(JXDatePicker.HOME_NAVIGATE_KEY)); } assertKeyBindings(linkPanel, JXDatePicker.HOME_COMMIT_KEY, bound); assertKeyBindings(linkPanel, JXDatePicker.HOME_NAVIGATE_KEY, bound); } /** * PENDING: move to testUtils. * @param comp * @param actionKey */ public void assertKeyBindings(JComponent comp, Object actionKey, boolean bound) { boolean hasAncestorBinding = hasBinding( comp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT), actionKey); boolean hasFocusedBinding = hasBinding( comp.getInputMap(JComponent.WHEN_FOCUSED), actionKey); boolean hasInFocusedBinding = hasBinding( comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW), actionKey); boolean hasBinding = hasAncestorBinding || hasFocusedBinding || hasInFocusedBinding; assertEquals("component has keybinding for " + actionKey, bound, hasBinding); } /** * * PENDING: move to testutils. * @param map * @param actionKey */ public boolean hasBinding(InputMap map, Object actionKey) { KeyStroke[] keyStrokes = map.keys(); if (keyStrokes != null) { for (KeyStroke stroke : keyStrokes) { if (actionKey.equals(map.get(stroke))) { return true; } } } return false; } /** * test that the toggle popup is registered in the * picker's actionMap. * * Issue #596-swingx: don't use space to open popup. */ @Test public void testTogglePopupAction() { JXDatePicker picker = new JXDatePicker(); Action togglePopup = picker.getActionMap().get("TOGGLE_POPUP"); assertNotNull(togglePopup); KeyStroke space = KeyStroke.getKeyStroke("alt DOWN"); Object actionKey = picker.getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) .get(space); assertEquals(actionKey, "TOGGLE_POPUP"); } /** * Characterization: when does picker fire action events? * * Test that set date programmatically (directly or indirectly) * does not fire an actionEvent. */ @Test public void testSetDateSilently() { JXDatePicker picker = new JXDatePicker(); ActionReport report = new ActionReport(); picker.addActionListener(report); // via editor Date value = XTestUtils.getStartOfToday(3); picker.getEditor().setValue(value); assertEquals(value, picker.getDate()); // via selection Date selected = XTestUtils.getStartOfToday(4); picker.getMonthView().setSelectionInterval(selected, selected); assertEquals(selected, picker.getDate()); Date date = XTestUtils.getStartOfToday(5); // directly picker.setDate(date); assertEquals(date, picker.getDate()); assertEquals(0, report.getEventCount()); } /** * Enhanced commit/cancel. * * test the cancel produced by the monthview trigger * cancel in the picker. * */ @Test public void testCommitCancelFromMonthViewCancel() { JXDatePicker picker = new JXDatePicker(); final ActionReport report = new ActionReport(); picker.addActionListener(report); Action cancelAction = picker.getMonthView().getActionMap().get(JXMonthView.CANCEL_KEY); cancelAction.actionPerformed(null); assertEquals("must have receive 1 event after monthView cancel", 1, report.getEventCount()); assertEquals(JXDatePicker.CANCEL_KEY, report.getLastActionCommand()); } /** * Enhanced commit/cancel. * * test the commit produced by the monthview trigger * commit in the picker. * */ @Test public void testCommitCancelFromMonthViewCommit() { JXDatePicker picker = new JXDatePicker(); Action commitAction = picker.getMonthView().getActionMap().get(JXMonthView.COMMIT_KEY); final ActionReport report = new ActionReport(); picker.addActionListener(report); commitAction.actionPerformed(null); assertEquals("must have receive 1 event after monthView commit", 1, report.getEventCount()); assertEquals(JXDatePicker.COMMIT_KEY, report.getLastActionCommand()); } /** * Enhanced commit/cancel. * * test that the ui installed a listener. */ @Test public void testCommitCancelListeningToMonthView() { JXMonthView monthView = new JXMonthView(); int standalone = monthView.getListeners(ActionListener.class).length; assertEquals(0, standalone); JXDatePicker picker = new JXDatePicker(); int contained = picker.getMonthView().getListeners(ActionListener.class).length; assertEquals(standalone + 1, contained); } /** * test wrapping and resetting the editors cancel action. * internals ... mostly to be sure about cleanup and re-wire. */ @Test public void testCancelEditorAction() { JFormattedTextField field = new JFormattedTextField(new DatePickerFormatter()); // original action Action original = field.getActionMap().get(EditorCancelAction.TEXT_CANCEL_KEY); assertNotNull(original); JXDatePicker picker = new JXDatePicker(); JFormattedTextField editor = picker.getEditor(); Action wrapper = editor.getActionMap().get(EditorCancelAction.TEXT_CANCEL_KEY); // wrapper installed assertTrue("PickerUI installed the wrapper action", wrapper instanceof EditorCancelAction); // set editor to field picker.setEditor(field); // old editor back to original assertSame("original action must be reset on setEditor", original, editor.getActionMap().get(EditorCancelAction.TEXT_CANCEL_KEY)); Action otherWrapper = field.getActionMap().get(EditorCancelAction.TEXT_CANCEL_KEY); assertTrue(otherWrapper instanceof EditorCancelAction); // created a new one assertNotSame(wrapper, otherWrapper); // uninstall picker.getUI().uninstallUI(picker); assertSame("original action must be reset on uninstall", original, field.getActionMap().get(EditorCancelAction.TEXT_CANCEL_KEY)); } /** * Enhanced commit/cancel. * * test that cancel action reverts silently: date related * state unchanged and no events fired (except the actionEvent). * */ @Test public void testCancelEditRevertsSilently() { JXDatePicker picker = new JXDatePicker(new Date()); String text = picker.getEditor().getText(); // manipulate the text, not entirely safe ... String changed = text.replace('0', '1'); picker.getEditor().setText(changed); final ActionReport actionReport = new ActionReport(); picker.addActionListener(actionReport); picker.getEditor().addActionListener(actionReport); picker.getMonthView().addActionListener(actionReport); final PropertyChangeReport propertyReport = new PropertyChangeReport(); picker.addPropertyChangeListener(propertyReport); picker.getEditor().addPropertyChangeListener(propertyReport); picker.cancelEdit(); assertEquals(0, propertyReport.getEventCount()); assertEquals(1, actionReport.getEventCount()); } /** * Enhanced commit/cancel. * * test that cancel fires as expected. * PENDING: need to invoke ... safe test? * */ @Test public void testCommitCancelActionsFireCancel() { JXDatePicker picker = new JXDatePicker(); final ActionReport report = new ActionReport(); picker.addActionListener(report); Action cancelAction = picker.getActionMap().get(JXDatePicker.CANCEL_KEY); cancelAction.actionPerformed(null); assertEquals(1, report.getEventCount()); assertEquals(JXDatePicker.CANCEL_KEY, report.getLastActionCommand()); } /** * Enhanced commit/cancel. * * test that commit fires as expected. * PENDING: need to invoke ... safe test? */ @Test public void testCommitCancelActionsFireCommit() { JXDatePicker picker = new JXDatePicker(); Action commitAction = picker.getActionMap().get(JXDatePicker.COMMIT_KEY); final ActionReport report = new ActionReport(); picker.addActionListener(report); commitAction.actionPerformed(null); assertEquals(1, report.getEventCount()); assertEquals(JXDatePicker.COMMIT_KEY, report.getLastActionCommand()); } /** * Enhanced commit/cancel. * * test that actions are registered. * */ @Test public void testCommitCancelActionExist() { JXDatePicker picker = new JXDatePicker(); assertNotNull(picker.getActionMap().get(JXDatePicker.CANCEL_KEY)); assertNotNull(picker.getActionMap().get(JXDatePicker.COMMIT_KEY)); } /** * Issue #658-swingx: timezone in linkformat updated. * * linkDate synced with monthView's today after setting. */ @Test public void testLinkDateSetToday() { JXDatePicker picker = new JXDatePicker(); Calendar cal = picker.getMonthView().getCalendar(); cal.setTime(picker.getMonthView().getToday()); cal.add(Calendar.MONTH, 1); CalendarUtils.endOfDay(cal); // NOTE: no public api, testing to guarantee the synch in all cases picker.getMonthView().setToday(cal.getTime()); assertEquals(picker.getMonthView().getToday(), picker.getLinkDay()); } /** * Issue #658-swingx: timezone in linkformat updated. * * Initial linkDate synced with monthView's today. */ @Test public void testLinkDateInitial() { JXDatePicker picker = new JXDatePicker(); assertEquals(picker.getMonthView().getToday(), picker.getLinkDay()); } /** * Issue #658-swingx: timezone in linkformat updated. * * Here: set timezone in picker. */ @Test public void testSynchTimeZoneLinkFormatOnModified() { JXDatePicker picker = new JXDatePicker(); TimeZone alternative = getSafeAlternativeTimeZone(picker.getTimeZone()); picker.setTimeZone(alternative); assertTimeZoneLinkFormat(picker, alternative); } /** * Issue #554-swingx: timezone of formats and picker must be synched. * Here: set monthView with alternative timezone */ @Test public void testSynchTimeZoneLinkFormatOnSetMonthView() { JXDatePicker picker = new JXDatePicker(); TimeZone defaultZone = picker.getTimeZone(); TimeZone alternative = getSafeAlternativeTimeZone(defaultZone); JXMonthView monthView = new JXMonthView(); monthView.setTimeZone(alternative); picker.setMonthView(monthView); assertTimeZoneLinkFormat(picker, alternative); } /** * Assert that all DateFormats in the picker's linkFormat have the same * timezone as the picker. * * @param picker the JXDatePicker to test * @param alternative the expected timeZone of the picker (for sanity only) */ private void assertTimeZoneLinkFormat(JXDatePicker picker, TimeZone alternative) { // sanity: picker has timezone as expected assertEquals("expected timezone in picker", alternative, picker.getTimeZone()); MessageFormat format = picker.getLinkFormat(); for (Format subFormat : format.getFormats()) { if (subFormat instanceof DateFormat) { assertEquals(picker.getTimeZone(), ((DateFormat) subFormat).getTimeZone()); } } } /** * Issue #554-swingx: timezone of formats and picker must be synched. * Here: set the timezone in the monthView. */ @Test public void testSynchTimeZoneModifiedInMonthView() { JXDatePicker picker = new JXDatePicker(); TimeZone defaultZone = picker.getTimeZone(); TimeZone alternative = getSafeAlternativeTimeZone(defaultZone); picker.getMonthView().setTimeZone(alternative); assertTimeZoneDateFormats(picker, alternative); } /** * Issue #554-swingx: timezone of formats and picker must be synched. * * Here: set the timezone in the picker. */ @Test public void testSynchTimeZoneModifiedInPicker() { JXDatePicker picker = new JXDatePicker(); TimeZone defaultZone = picker.getTimeZone(); TimeZone alternative = getSafeAlternativeTimeZone(defaultZone); picker.setTimeZone(alternative); assertTimeZoneDateFormats(picker, alternative); } /** * Issue #554-swingx: timezone of formats and picker must be synched. * Here: set the timezone in the picker. */ @Test public void testSynchTimeZoneOnSetMonthView() { JXDatePicker picker = new JXDatePicker(); TimeZone defaultZone = picker.getTimeZone(); TimeZone alternative = getSafeAlternativeTimeZone(defaultZone); JXMonthView monthView = new JXMonthView(); monthView.setTimeZone(alternative); picker.setMonthView(monthView); assertTimeZoneDateFormats(picker, alternative); } /** * Issue #554-swingx: timezone of formats and picker must be synched. * * Here: initialize the formats with the pickers timezone on setting. */ @Test public void testSynchTimeZoneOnSetFormats() { JXDatePicker picker = new JXDatePicker(); TimeZone defaultZone = picker.getTimeZone(); TimeZone alternative = getSafeAlternativeTimeZone(defaultZone); picker.setTimeZone(alternative); picker.setFormats(DateFormat.getDateInstance()); assertTimeZoneDateFormats(picker, alternative); } /** * Assert that all DateFormats in the picker's linkFormat have the same * timezone as the picker. * * @param picker the JXDatePicker to test * @param alternative the expected timeZone of the picker (for sanity only) */ private void assertTimeZoneDateFormats(JXDatePicker picker, TimeZone alternative) { assertEquals(alternative, picker.getTimeZone()); for (DateFormat format : picker.getFormats()) { assertEquals("timezone must be synched", picker.getTimeZone(), format.getTimeZone()); } } /** * Issue #554-swingx: timezone of formats and picker must be synched. */ @Test public void testSynchTimeZoneInitial() { JXDatePicker picker = new JXDatePicker(); assertNotNull(picker.getTimeZone()); for (DateFormat format : picker.getFormats()) { assertEquals("timezone must be synched", picker.getTimeZone(), format.getTimeZone()); } } /** * Test doc'ed behaviour: editor must not be null. */ @Test public void testEditorNull() { JXDatePicker picker = new JXDatePicker(); assertNotNull(picker.getEditor()); try { picker.setEditor(null); fail("picker must throw NPE if editor is null"); } catch (NullPointerException e) { // nothing to do - doc'ed behaviour } } /** * Test doc'ed behaviour: editor must not be null. */ @Test public void testMonthViewNull() { JXDatePicker picker = new JXDatePicker(); assertNotNull(picker.getMonthView()); try { picker.setMonthView(null); fail("picker must throw NPE if monthView is null"); } catch (NullPointerException e) { // nothing to do - doc'ed behaviour } } /** * picker has cleaned date, clarified doc. * The test is not exactly true, the details * are up for the DatePickerUI to decide. * */ @Test public void testSetDateCleansDate() { JXDatePicker picker = new JXDatePicker(); Date date = calendar.getTime(); picker.setDate(date); assertEquals(CalendarUtils.startOfDay(calendar, date), picker.getDate()); } /** * Regression testing: make sure the passed-in date is not changed. * */ @Test public void testSetDateDoesNotChangeOriginal() { JXDatePicker picker = new JXDatePicker(); Date date = calendar.getTime(); Date copy = new Date(date.getTime()); picker.setDate(date); assertEquals(copy, date); } /** * date is a bound property of DatePicker. */ @Test public void testDateProperty() { JXDatePicker picker = new JXDatePicker(); Date date = XTestUtils.getStartOfToday(5); PropertyChangeReport report = new PropertyChangeReport(); picker.addPropertyChangeListener("date", report); picker.setDate(date); TestUtils.assertPropertyChangeEvent(report, "date", null, date); } /** * date is a bound property of DatePicker. * test indirect event firing: changed editor value */ @Test public void testDatePropertyThroughEditor() { JXDatePicker picker = new JXDatePicker(); Date date = XTestUtils.getStartOfToday(5); PropertyChangeReport report = new PropertyChangeReport(); picker.addPropertyChangeListener("date", report); picker.getEditor().setValue(date); TestUtils.assertPropertyChangeEvent(report, "date", null, date); } /** * date is a bound property of DatePicker. * test indirect event firing: changed monthView selection */ @Test public void testDatePropertyThroughSelection() { JXDatePicker picker = new JXDatePicker(); Date date = XTestUtils.getStartOfToday(5); PropertyChangeReport report = new PropertyChangeReport(); picker.addPropertyChangeListener("date", report); picker.getMonthView().setSelectionInterval(date, date); TestUtils.assertPropertyChangeEvent(report, "date", null, date); } /** * date is a bound property of DatePicker. * test indirect event firing: commit edited value * @throws ParseException * */ @Test public void testDatePropertyThroughCommit() throws ParseException { JXDatePicker picker = new JXDatePicker(new Date()); Date initialDate = picker.getDate(); String text = picker.getEditor().getText(); Format[] formats = picker.getFormats(); assertEquals(picker.getDate(), formats[0].parseObject(text)); // manipulate the text, not entirely safe ... String changed = text.replace('0', '1'); picker.getEditor().setText(changed); Date date; try { date = (Date) formats[0].parseObject(changed); } catch (ParseException e) { LOG.info("cannot run DatePropertyThroughCommit - parseException in manipulated text"); return; } // sanity ... assertFalse("", date.equals(picker.getDate())); PropertyChangeReport report = new PropertyChangeReport(); picker.addPropertyChangeListener("date", report); picker.commitEdit(); TestUtils.assertPropertyChangeEvent(report, "date", initialDate, date); } /** * last piece: removed synch control from picker.commit. * @throws ParseException * */ @Test public void testSynchAllAfterCommit() throws ParseException { JXDatePicker picker = new JXDatePicker(new Date()); String text = picker.getEditor().getText(); Format[] formats = picker.getFormats(); assertEquals(picker.getDate(), formats[0].parseObject(text)); // manipulate the text, not entirely safe ... String changed = text.replace('0', '1'); picker.getEditor().setText(changed); Date date; try { date = (Date) formats[0].parseObject(changed); } catch (ParseException e) { LOG.info("cannot run testSynchAllAfterCommit - parseException in manipulated text"); return; } // sanity ... assertFalse("", date.equals(picker.getDate())); picker.commitEdit(); assertSynchAll(picker, date); } /** * Issue #559-swingX: date must be synched in all parts. * here: initial. * */ @Test public void testSynchAllInitialDate() { Date date = XTestUtils.getStartOfToday(5); JXDatePicker picker = new JXDatePicker(date); assertSynchAll(picker, date); } /** * Issue #559-swingX: date must be synched in all parts. * here: set date in picker * * Note: test uses a cleaned date, do same with uncleaned. */ @Test public void testSynchAllOnDateModified() { JXDatePicker picker = new JXDatePicker(); Date date = XTestUtils.getStartOfToday(5); picker.setDate(date); assertSynchAll(picker, date); } /** * Issue #559-swingX: date must be synched in all parts. * here: set selected date in monthview * Note: test uses a cleaned date, do same with uncleaned. */ @Test public void testSynchAllOnSelectionChange() { JXDatePicker picker = new JXDatePicker(); Date date = XTestUtils.getStartOfToday(5); picker.getMonthView().setSelectionInterval(date, date); assertSynchAll(picker, date); } /** * Issue #559-swingX: date must be synched in all parts. * here: set value in editor. * * Note: test uses a cleaned date, do same with uncleaned. */ @Test public void testSynchAllOnEditorSetValue() { JXDatePicker picker = new JXDatePicker(); Date date = XTestUtils.getStartOfToday(5); picker.getEditor().setValue(date); assertSynchAll(picker, date); } /** * Issue #559-swingX: date must be synched in all parts. * here: modify value must work after changing the editor. * * Note: this started to fail during listener cleanup. */ @Test public void testSynchAllOnEditorSetValueAfterSetEditor() { JXDatePicker picker = new JXDatePicker(); picker.setEditor(new JFormattedTextField(DateFormat.getInstance())); Date date = XTestUtils.getStartOfToday(5); picker.getEditor().setValue(date); assertSynchAll(picker, date); } /** * Issue #559-swingX: date must be synched in all parts. * here: set selection must work after changing the monthView. * * Note: this started to fail during listener cleanup. */ @Test public void testSynchAllOnSelectionChangeAfterSetMonthView() { JXDatePicker picker = new JXDatePicker(); picker.setMonthView(new JXMonthView()); Date date = XTestUtils.getStartOfToday(5); picker.getMonthView().setSelectionInterval(date, date); assertSynchAll(picker, date); } /** * Issue #559-swingX: date must be synched in all parts. * <p> * * here: set selection must work after changing the monthView's selection * model. * * Note: this started to fail during listener cleanup. */ @Test public void testSynchAllOnSelectionChangeAfterSetSelectionModel() { JXDatePicker picker = new JXDatePicker(); picker.getMonthView().setSelectionModel(new DefaultDateSelectionModel()); Date date = XTestUtils.getStartOfToday(5); picker.getMonthView().setSelectionInterval(date, date); assertSynchAll(picker, date); } /** * Asserts that all date related values in the picker are synched. * * @param picker the picker to * @param date the common date */ private void assertSynchAll(JXDatePicker picker, Date date) { assertEquals(date, picker.getEditor().getValue()); assertEquals(date, picker.getDate()); assertEquals(date, picker.getMonthView().getSelectionDate()); // @KEEP JW - currently unused, not yet sure if it's the right place // for checking against ripples produced by fixing #705-swingx Calendar cal = picker.getMonthView().getCalendar(); if (date == null) { cal.setTime(picker.getLinkDay()); CalendarUtils.startOfMonth(cal); } else { cal.setTime(date); CalendarUtils.startOfMonth(cal); } assertEquals(cal.getTime(), picker.getMonthView().getFirstDisplayedDay()); } /** * test that input of unselectable dates reverts editors value. */ @Test public void testRejectSetValueUnselectable() { JXDatePicker picker = new JXDatePicker(); Date upperBound = XTestUtils.getStartOfToday(1); picker.getMonthView().setUpperBound(upperBound); Date future = XTestUtils.getStartOfToday(2); // sanity assertTrue(picker.getMonthView().isUnselectableDate(future)); Date current = picker.getDate(); // sanity: assertEquals(current, picker.getEditor().getValue()); // set the editors value to something invalid picker.getEditor().setValue(future); // ui must not allow an invalid value in the editor assertEquals(current, picker.getEditor().getValue()); // okay .. assertEquals(current, picker.getDate()); } /** * PickerUI listened to editable (meant: datePicker) and resets * the editors property. Accidentally? Even if meant to, it's * brittle because done during the notification. * Changed to use dedicated listener. */ @Test public void testSpuriousEditableListening() { JXDatePicker picker = new JXDatePicker(); picker.getEditor().setEditable(false); // sanity - that at least the other views are uneffected assertTrue(picker.isEditable()); assertTrue(picker.getMonthView().isEnabled()); assertFalse("Do not change the state of the sender during notification processing", picker.getEditor().isEditable()); } /** * PickerUI listened to enabled of button (meant: datePicker) and resets * the buttons property. */ @Test public void testSpuriousEnabledListening() { JXDatePicker picker = new JXDatePicker(); Component button = null; for (int i = 0; i < picker.getComponentCount(); i++) { if (picker.getComponent(i) instanceof JButton) { button = picker.getComponent(i); } } if (button == null) { LOG.info("cannot run testEnabledListening - no button found"); return; } button.setEnabled(false); // sanity - that at least the other views are uneffected assertTrue(picker.isEnabled()); assertTrue(picker.getEditor().isEnabled()); assertFalse("Do not change the state of the sender during notification processing", button.isEnabled()); } /** * Sanity during revision: be sure we don't loose the * ui listening to picker property changes. * */ @Test public void testDatePickerPropertyListening() { JXDatePicker picker = new JXDatePicker(); picker.setEnabled(false); assertFalse(picker.getEditor().isEnabled()); picker.setEditable(false); assertFalse(picker.getEditor().isEditable()); picker.setToolTipText("dummy"); assertEquals("dummy", picker.getEditor().getToolTipText()); } /** * Issue ??-swingx: uninstallUI does not release propertyChangeListener * to editor. Reason is that the de-install was not done in * uninstallListeners but later in uninstallComponents - at that time * the handler is already nulled, removing will actually create a new one. */ @Test public void testEditorListeners() { JFormattedTextField field = new JFormattedTextField(DateFormat.getInstance()); JXDatePicker picker = new JXDatePicker(); int defaultListenerCount = field.getPropertyChangeListeners().length; // sanity: we added one listener ... assertEquals(defaultListenerCount + 1, picker.getEditor().getPropertyChangeListeners().length); picker.getUI().uninstallUI(picker); assertEquals("the ui installe listener must be removed", defaultListenerCount, // right now we can access the editor even after uninstall // because the picker keeps a reference // TODO: after cleanup, this will be done through the ui picker.getEditor().getPropertyChangeListeners().length); } /** * Issue #551-swingX: editor value not updated after setMonthView. * * quick&dirty fix: let the picker manually update. * */ @Test public void testEditorValueOnSetMonthView() { JXDatePicker picker = new JXDatePicker(new Date()); // set unselected monthView picker.setMonthView(new JXMonthView()); // sanity: picker takes it assertNull(picker.getDate()); assertEquals(picker.getDate(), picker.getEditor().getValue()); } /** * Issue #551-swingx: editor value not updated after setEditor. * * quick&dirty fix: let the picker manually update. * * who should set it? ui-delegate when listening to editor property change? * or picker in setEditor? * * Compare to JComboBox: BasicComboUI listens to editor change, does internal * wiring to editor and call's comboBox configureEditor with the value of the * old editor. * * */ @Test public void testEditorValueOnSetEditor() { JXDatePicker picker = new JXDatePicker(); Object value = picker.getEditor().getValue(); picker.setEditor(new JFormattedTextField(new DatePickerFormatter())); assertEquals(value, picker.getEditor().getValue()); } /** * Issue #551-swingx: editor value must preserve value on LF switch. * * This is a side-effect of picker not updating the editor's value * on setEditor. * * @see #testEditorValueOnSetEditor */ @Test public void testEditorUpdateOnLF() { JXDatePicker picker = new JXDatePicker(); Object date = picker.getEditor().getValue(); picker.updateUI(); assertEquals(date, picker.getEditor().getValue()); } @Test public void testEditorUIResource() { JXDatePicker picker = new JXDatePicker(); // this is safe: ui must install an editor and it must be of type UIResource assertEquals("default editor is UIResource ", true, picker.getEditor() instanceof UIResource); JFormattedTextField editor = new JFormattedTextField(); picker.setEditor(editor); assertEquals("sanity: custom editor not UIResource ", false, picker.getEditor() instanceof UIResource); picker.updateUI(); assertSame("updateUI must not touch custom editor", editor, picker.getEditor()); } /** * Characterization: setting the monthview's selection model updates * the datePicker's date to the monthView's current * selection. * * Here: model with selection. * */ @Test public void testSynchAllAfterSetSelectionModelNotEmpty() { JXDatePicker picker = new JXDatePicker(); Date date = XTestUtils.getStartOfToday(5); DateSelectionModel model = new DefaultDateSelectionModel(); model.setSelectionInterval(date, date); // sanity assertFalse(date.equals(picker.getDate())); picker.getMonthView().setSelectionModel(model); assertSynchAll(picker, date); } /** * Characterization: setting the monthview's selection model updates * the datePicker's date to the monthView's current * selection. * * Here: model with empty selection. * */ @Test public void testSynchAllAfterSetSelectionModelEmpty() { JXDatePicker picker = new JXDatePicker(new Date()); assertNotNull(picker.getDate()); DateSelectionModel model = new DefaultDateSelectionModel(); assertTrue(model.isSelectionEmpty()); picker.getMonthView().setSelectionModel(model); assertSynchAll(picker, null); } /** * Characterization: setting the monthview updates * the datePicker's date to the monthView's current * selection. * Here: monthview with selection. * */ @Test public void testSynchAllSetMonthViewWithSelection() { JXDatePicker picker = new JXDatePicker(); JXMonthView monthView = new JXMonthView(); Date date = XTestUtils.getStartOfToday(5); monthView.setSelectionInterval(date, date); // sanity assertFalse(date.equals(picker.getDate())); picker.setMonthView(monthView); assertSynchAll(picker, date); } /** * Characterization: setting the monthview updates * the datePicker's date to the monthView's current * selection. * Here: monthview with empty selection. * */ @Test public void testSynchAllSetMonthViewWithEmptySelection() { JXDatePicker picker = new JXDatePicker(new Date()); // sanity assertNotNull(picker.getDate()); JXMonthView monthView = new JXMonthView(); Date selectedDate = monthView.getSelectionDate(); assertNull(selectedDate); picker.setMonthView(monthView); assertSynchAll(picker, selectedDate); } /** * Issue #1292-swingx: prefsize growing on inserting text into empty editor. * * PrefSize should be independent of empty/filled picker. * If not, the initial size might appear kind of collapsed. * */ @Test public void testMinSizeEqualsPrefSize() { JXDatePicker picker = new JXDatePicker(new Date()); assertEquals("pref/min expected equal", picker.getEditor().getPreferredSize().width, picker.getEditor().getMinimumSize().width); picker.getEditor().setText("1"); assertEquals("pref/min expected equal", picker.getEditor().getPreferredSize().width, picker.getEditor().getMinimumSize().width); picker.setDate(null); assertEquals("pref/min expected equal", picker.getEditor().getPreferredSize().width, picker.getEditor().getMinimumSize().width); } /** * Issue #1292-swingx: prefsize growing on inserting text into empty editor. * * PrefSize should be independent of empty/filled picker. * If not, the initial size might appear kind of collapsed. * */ @Test public void testPrefSizeEmptyInsertText() { JXDatePicker picker = new JXDatePicker(); Dimension empty = picker.getPreferredSize(); // simulate editing (uncommitted) picker.getEditor().setText("1"); assertEquals("pref width must be same while editing", empty.width, picker.getPreferredSize().width); } /** * Issue #1292-swingx: prefsize growing on inserting text into empty editor. * * PrefSize should be independent of empty/filled picker. * If not, the initial size might appear kind of collapsed. * */ @Test public void testPrefSizeValueInsertText() { // initial size with value JXDatePicker picker = new JXDatePicker(new Date()); Dimension withValue = picker.getPreferredSize(); // simulate editing (uncommitted) picker.getEditor().setText("1"); assertEquals("pref width must be same while editing", withValue.width, picker.getPreferredSize().width); } /** * PrefSize should be independent of empty/filled picker. * If not, the initial size might appear kind of collapsed. * */ @Test public void testPrefSizeEmptyEditor() { JXDatePicker picker = new JXDatePicker(new Date()); Dimension withValue = picker.getPreferredSize(); // null value picker.setDate(null); assertEquals("pref width must be same null value", withValue.width, picker.getPreferredSize().width); } @Test public void testDefaultConstructor() { JXDatePicker datePicker = new JXDatePicker(); assertNull(datePicker.getDate()); } @Test public void testConstructor() { calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.DAY_OF_MONTH, 5); Date expectedDate = cleanupDate(calendar); JXDatePicker datePicker = new JXDatePicker(calendar.getTime()); assertTrue(expectedDate.equals(datePicker.getDate())); } @Test public void testNullSelection() { JXDatePicker datePicker = new JXDatePicker(); assertTrue(null == datePicker.getDate()); } @Test public void testSetDate() { calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.DAY_OF_MONTH, 5); Date expectedDate = cleanupDate(calendar); JXDatePicker datePicker = new JXDatePicker(); datePicker.setDate(calendar.getTime()); assertTrue(expectedDate.equals(datePicker.getDate())); assertTrue(expectedDate.equals(datePicker.getEditor().getValue())); datePicker.setDate(null); assertTrue(null == datePicker.getDate()); assertTrue(null == datePicker.getEditor().getValue()); } //------------------ test helpers /** * Returns a timezone different from the given. * @param defaultZone * @return */ private TimeZone getSafeAlternativeTimeZone(TimeZone defaultZone) { TimeZone alternative = TimeZone.getTimeZone("GMT-6"); // sanity assertNotNull(alternative); if (alternative.equals(defaultZone)) { alternative = TimeZone.getTimeZone("GMT-7"); // paranoid ... but shit happens assertNotNull(alternative); assertFalse(alternative.equals(defaultZone)); } return alternative; } private Date cleanupDate(Calendar cal) { cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } @Override @Before public void setUp() { calendar = Calendar.getInstance(); } @Override @After public void tearDown() { } }