001: /*
002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.binding.tests;
032:
033: import java.util.Arrays;
034:
035: import javax.swing.DefaultListModel;
036:
037: import junit.framework.TestCase;
038:
039: import com.jgoodies.binding.adapter.ComboBoxAdapter;
040: import com.jgoodies.binding.list.SelectionInList;
041: import com.jgoodies.binding.tests.event.ListDataReport;
042: import com.jgoodies.binding.value.ValueHolder;
043: import com.jgoodies.binding.value.ValueModel;
044:
045: /**
046: * Tests the {@link ComboBoxAdapter}.
047: *
048: * @author Karsten Lentzsch
049: * @version $Revision: 1.26 $
050: *
051: * @see ComboBoxAdapter
052: */
053: public final class ComboBoxAdapterTest extends TestCase {
054:
055: private static final String[] AN_ARRAY = { "one", "two", "three" };
056:
057: private DefaultListModel listModel;
058: private SelectionInList<String> selectionInList;
059: private ValueModel selectionHolder;
060:
061: private ComboBoxAdapter<String> combo;
062: private ListDataReport report;
063:
064: @Override
065: protected void setUp() throws Exception {
066: super .setUp();
067: initComboWithListModel();
068: }
069:
070: @Override
071: protected void tearDown() throws Exception {
072: super .tearDown();
073: listModel = null;
074: combo = null;
075: selectionInList = null;
076: report = null;
077: }
078:
079: /**
080: * Checks that the constructors reject null selectionHolders with a NPE.
081: */
082: public void testConstructorRejectsNullValues() {
083: final String message = "Constructor must throw NPE on null selectionHolder.";
084: try {
085: new ComboBoxAdapter<String>(listModel, null);
086: fail(message);
087: } catch (NullPointerException e) {
088: // the expected behaviour
089: }
090: try {
091: new ComboBoxAdapter<String>(AN_ARRAY, null);
092: fail(message);
093: } catch (NullPointerException e) {
094: // the expected behaviour
095: }
096: try {
097: new ComboBoxAdapter<String>(Arrays.asList(AN_ARRAY), null);
098: fail(message);
099: } catch (NullPointerException e) {
100: // the expected behaviour
101: }
102: try {
103: new ComboBoxAdapter<String>((SelectionInList<String>) null);
104: fail("Constructor must reject a null selectionInList.");
105: } catch (NullPointerException e) {
106: // the expected behaviour
107: }
108: }
109:
110: /**
111: * Tests that the event source for all events fired by
112: * ComboBoxModel operations is the ComboBoxModel.
113: */
114: public void testEventSource() {
115: final String message = "The event source must be the combo box model.";
116: assertEquals("Initial size must be " + AN_ARRAY.length,
117: AN_ARRAY.length, combo.getSize());
118: listModel.addElement("some");
119: assertEquals(message, combo, report.lastEvent().getSource());
120: listModel.remove(0);
121: assertEquals(message, combo, report.lastEvent().getSource());
122: listModel.setElementAt("newElement", 0);
123: assertEquals(message, combo, report.lastEvent().getSource());
124: combo.setSelectedItem("three");
125: assertEquals(message, combo, report.lastEvent().getSource());
126: }
127:
128: /**
129: * Checks that manipulations on the underlying ListModel
130: * throw one event only, or in other words: avoid duplicate events.
131: */
132: public void testOneEventOnListModelManipulation() {
133: assertOneEventOnListModelManipulation();
134: listModel = createListModel(AN_ARRAY);
135: selectionInList = new SelectionInList<String>(listModel);
136: initComboWithSelectionInList();
137: assertOneEventOnListModelManipulation();
138: }
139:
140: private void assertOneEventOnListModelManipulation() {
141: listModel.addElement("some");
142: assertEquals("event count", 1, report.eventCount());
143: listModel.removeElementAt(0);
144: assertEquals("event count", 2, report.eventCount());
145: listModel.setElementAt("newElement", 0);
146: assertEquals("event count", 3, report.eventCount());
147: }
148:
149: // public void testInitialSelectionInList() {
150: // selectionHolder.setValue(listModel.getElementAt(1));
151: // SelectionInList sil = new SelectionInList(listModel);
152: // combo = new ComboBoxAdapter(sil, selectionHolder);
153: // assertEquals("Selection index shall reflect the initial selection.",
154: // 1,
155: // sil.getSelectionIndex());
156: // }
157: //
158: // public void testInitialSelectionInCombo() {
159: // selectionHolder.setValue("notInList");
160: // SelectionInList sil = new SelectionInList(listModel);
161: // sil.setSelectionIndex(1);
162: // combo = new ComboBoxAdapter(sil, selectionHolder);
163: // assertEquals("Selection index shall reflect the initial selection.",
164: // -1,
165: // sil.getSelectionIndex());
166: // }
167:
168: /**
169: * Checks that a selection action throws one event only.
170: */
171: public void testOneEventOnComboSelection() {
172: assertOneEventOnComboSelection();
173: initComboWithArray();
174: assertOneEventOnComboSelection();
175: initComboWithList();
176: assertOneEventOnComboSelection();
177: initComboWithSelectionInList();
178: assertOneEventOnComboSelection();
179: }
180:
181: private void assertOneEventOnComboSelection() {
182: combo.setSelectedItem("three");
183: assertEquals("event count", 1, report.eventCount());
184: }
185:
186: /**
187: * Checks that a change in the selection holder value throws one event only.
188: */
189: public void testOneEventOnHolderSelection() {
190: assertOneEventOnHolderSelection();
191: initComboWithArray();
192: assertOneEventOnHolderSelection();
193: initComboWithList();
194: assertOneEventOnHolderSelection();
195: }
196:
197: private void assertOneEventOnHolderSelection() {
198: selectionHolder.setValue("three");
199: assertEquals("event count", 1, report.eventCount());
200: }
201:
202: public void testAllowSelectionNotInList() {
203: combo.setSelectedItem("notInList");
204: assertEquals("combo must accept any selection", "notInList",
205: combo.getSelectedItem());
206: }
207:
208: /**
209: * Checks that an absent element should be rejected
210: * if the adapter is constructed with a selectionInList.
211: */
212: public void testRejectSelectionNotInList() {
213: initComboWithSelectionInList();
214: combo.setSelectedItem("notInList");
215: assertNull("combo must reject not contained elements", combo
216: .getSelectedItem());
217: }
218:
219: public void testChangeListSameSelection() {
220: initComboWithSelectionInList();
221: String[] anotherArray = new String[] { "one", "two", "three",
222: "four" };
223: selectionInList.setListModel(createListModel(anotherArray));
224: assertTrue(
225: "combo must fire at least one event, either 1 content change or a combination of add/remove or content/add or content/remove",
226: report.eventCount() >= 1);
227: }
228:
229: // Changing the Selection *************************************************
230:
231: /**
232: * Verifies that a ComboBoxAdapter built with a SelectionInList
233: * keeps the selection in synch with an underlying ListModel.
234: */
235: public void testSelectionAfterSetElement() {
236: initComboWithSelectionInList();
237: combo.setSelectedItem("two");
238: listModel.set(1, "other");
239: assertEquals("combo selection must be changed", "other", combo
240: .getSelectedItem());
241: }
242:
243: /**
244: * Verifies that a ComboBoxAdapter built with a selection holder
245: * won't update the selection if the underlying ListModel changes.
246: */
247: public void testSelectionAfterSetElementDecoupled() {
248: combo.setSelectedItem("two");
249: listModel.set(1, "other");
250: assertEquals("combo selection must be changed", "two", combo
251: .getSelectedItem());
252: }
253:
254: // Removing Items, Requires an Underlying ListModel ***********************
255:
256: public void testSelectionAfterRemoveBefore() {
257: testSelectionAfterRemove(AN_ARRAY[1], 0);
258: }
259:
260: public void testSelectionAfterRemoveAfter() {
261: testSelectionAfterRemove(AN_ARRAY[1], 2);
262: }
263:
264: /**
265: * Verifies that the selection will be cleared if
266: * it has been removed from the underlying list.
267: */
268: public void testSelectionAfterRemoveOn() {
269: initComboWithSelectionInList();
270: combo.setSelectedItem("two");
271: listModel.remove(1);
272: assertEquals("Combo's selection must be empty", null, combo
273: .getSelectedItem());
274: }
275:
276: /**
277: * Verifies that the selection holder is unchanged
278: * if the selection is removed from the underlying list.
279: */
280: public void testSelectionAfterRemoveOnDecoupled() {
281: combo.setSelectedItem("two");
282: listModel.remove(1);
283: assertEquals("Combo's selection must be empty", "two", combo
284: .getSelectedItem());
285: }
286:
287: public void testSelectionAfterRemoveUnrelated() {
288: testSelectionAfterRemove("notInList", 1);
289: }
290:
291: private void testSelectionAfterRemove(Object initialSelection,
292: int index) {
293: combo.setSelectedItem(initialSelection);
294: listModel.remove(index);
295: assertEquals(
296: "Combo's selection must be unchanged after remove",
297: initialSelection, combo.getSelectedItem());
298: }
299:
300: /**
301: * This is for comparison only:
302: * taking DefaultComboBoxModel as reference.
303: */
304: // public void testDefaultComboSelectionAfterRemoveOn() {
305: // DefaultComboBoxModel combo = new DefaultComboBoxModel(someArray);
306: // combo.setSelectedItem(someArray[1]);
307: // combo.removeElementAt(1);
308: // // PENDING: how independent is the combo selection? remove
309: // // if removed from list?
310: // // DefaultComboBoxModel moves selection to previous item
311: // assertEquals("pathological behaviour of DefaultComboBoxModel ", "two", combo.getSelectedItem());
312: //
313: // }
314: // Inserting Items, Requires an underlying ListModel **********************
315: public void testSelectionAfterInsertBefore() {
316: testSelectionAfterInsert(AN_ARRAY[1], 0);
317: }
318:
319: public void testSelectionAfterInsertAfter() {
320: testSelectionAfterInsert(AN_ARRAY[1], 2);
321: }
322:
323: public void testSelectionAfterInsertOn() {
324: testSelectionAfterInsert(AN_ARRAY[1], 1);
325: }
326:
327: public void testSelectionAfterInsertUnrelated() {
328: testSelectionAfterInsert("unrelated", 1);
329: }
330:
331: private void testSelectionAfterInsert(Object initialSelection,
332: int index) {
333: combo.setSelectedItem(initialSelection);
334: updateReport();
335: int oldSize = combo.getSize();
336: listModel.insertElementAt("another", index);
337: assertEquals(
338: "Combo's selection must be unchanged after insert",
339: initialSelection, combo.getSelectedItem());
340: assertEquals("size", oldSize + 1, combo.getSize());
341: }
342:
343: // List Changes, Requires an Underlying SelectionInList *******************
344:
345: /**
346: * Tests effects of setting new List when
347: * selectionInList controls selection.
348: */
349: public void testNewListWithSelectedItem() {
350: // selection is controlled by SelectionInList!
351: initComboWithSelectionInList();
352: combo.setSelectedItem("two");
353: updateReport();
354: Object[] array = { "totally", "different", "two", "content" };
355: selectionInList.setListModel(createListModel(array));
356: assertEquals("selection must be unchanged", "two", combo
357: .getSelectedItem());
358:
359: }
360:
361: /**
362: * Tests effects of setting new List when
363: * selectionInList controls selection.
364: */
365: public void testNewListWithoutSelectedItem() {
366: // The selection is controlled by SelectionInList!
367: initComboWithSelectionInList();
368: combo.setSelectedItem("two");
369: updateReport();
370: Object[] array = { "totally", "different", "content" };
371: selectionInList.setListModel(createListModel(array));
372: assertEquals("combo selection must be null", null, combo
373: .getSelectedItem());
374: }
375:
376: /**
377: * Tests effects of setting new List when
378: * selectionInList does not control selection.
379: */
380: /*
381: public void testNewListWithoutSelectedItemOldWasNotInList() {
382: // The selection is _not_ controlled by SelectionInList!
383: initComboWithSelectionInListAndSelection();
384: combo.setSelectedItem("notInList");
385: updateReport();
386: Object[] array = { "totally", "different", "content" };
387: selectionInList.setListModel(createListModel(array));
388: assertEquals("combo selection must be unchanged",
389: "notInList",
390: combo.getSelectedItem());
391: }
392: */
393:
394: /**
395: * Tests effects of setting new List when
396: * selectionInList does not control selection.
397: */
398: // public void testNewListWithoutSelectedItemOldWasInList() {
399: // // The selection is _not_ controlled by SelectionInList!
400: // initComboWithSelectionInListAndSelection();
401: // combo.setSelectedItem("one");
402: // updateReport();
403: // Object[] array = { "totally", "different", "content" };
404: // selectionInList.setListModel(createListModel(array));
405: // assertEquals("combo selection must be null", null, combo.getSelectedItem());
406: // }
407: //
408: //
409: // public void testChangeSelectionInList() {
410: // initComboWithSelectionInListAndSelection();
411: // selectionInList.setSelection(AN_ARRAY[0]);
412: // assertEquals(
413: // "combo selection must be updated to selectionInList selection",
414: // selectionInList.getSelection(),
415: // combo.getSelectedItem());
416: // assertEquals("combo must fire one contentsChanged",
417: // 1,
418: // report.eventCountChange());
419: // updateReport();
420: // combo.setSelectedItem("notInList");
421: // assertNull("selectionInList selection must be empty",
422: // selectionInList.getSelection());
423: // assertEquals("combo must fire one contentsChanged",
424: // 1,
425: // report.eventCountChange());
426: // selectionInList.setSelection(AN_ARRAY[1]);
427: // assertEquals("combo selection must (or not??) be synched",
428: // AN_ARRAY[1],
429: // combo.getSelectedItem());
430: // }
431: // Setup Helper Code ******************************************************
432: private void updateReport() {
433: report = new ListDataReport();
434: combo.addListDataListener(report);
435: }
436:
437: private void initComboWithSelectionInList() {
438: initBasicFields();
439: combo = new ComboBoxAdapter<String>(selectionInList);
440: updateReport();
441: }
442:
443: private void initComboWithArray() {
444: initBasicFields();
445: combo = new ComboBoxAdapter<String>(AN_ARRAY, selectionHolder);
446: updateReport();
447: }
448:
449: private void initComboWithListModel() {
450: initBasicFields();
451: combo = new ComboBoxAdapter<String>(listModel, selectionHolder);
452: updateReport();
453: }
454:
455: private void initComboWithList() {
456: initBasicFields();
457: combo = new ComboBoxAdapter<String>(Arrays.asList(AN_ARRAY),
458: selectionHolder);
459: updateReport();
460: }
461:
462: private void initBasicFields() {
463: listModel = createListModel(AN_ARRAY);
464: selectionInList = new SelectionInList<String>(listModel);
465: selectionHolder = new ValueHolder(null);
466: }
467:
468: private DefaultListModel createListModel(Object[] array) {
469: DefaultListModel model = new DefaultListModel();
470: for (Object element : array) {
471: model.addElement(element);
472: }
473: return model;
474: }
475:
476: }
|