001: /*
002: * This file is part of the Echo Web Application Framework (hereinafter "Echo").
003: * Copyright (C) 2002-2005 NextApp, Inc.
004: *
005: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
006: *
007: * The contents of this file are subject to the Mozilla Public License Version
008: * 1.1 (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: * http://www.mozilla.org/MPL/
011: *
012: * Software distributed under the License is distributed on an "AS IS" basis,
013: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
014: * for the specific language governing rights and limitations under the
015: * License.
016: *
017: * Alternatively, the contents of this file may be used under the terms of
018: * either the GNU General Public License Version 2 or later (the "GPL"), or
019: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
020: * in which case the provisions of the GPL or the LGPL are applicable instead
021: * of those above. If you wish to allow use of your version of this file only
022: * under the terms of either the GPL or the LGPL, and not to allow others to
023: * use your version of this file under the terms of the MPL, indicate your
024: * decision by deleting the provisions above and replace them with the notice
025: * and other provisions required by the GPL or the LGPL. If you do not delete
026: * the provisions above, a recipient may use your version of this file under
027: * the terms of any one of the MPL, the GPL or the LGPL.
028: */
029:
030: package nextapp.echo2.app.test;
031:
032: import java.util.Arrays;
033: import java.util.List;
034:
035: import nextapp.echo2.app.Alignment;
036: import nextapp.echo2.app.ApplicationInstance;
037: import nextapp.echo2.app.Color;
038: import nextapp.echo2.app.Command;
039: import nextapp.echo2.app.Component;
040: import nextapp.echo2.app.Label;
041: import nextapp.echo2.app.Column;
042: import nextapp.echo2.app.TextField;
043: import nextapp.echo2.app.layout.ColumnLayoutData;
044: import nextapp.echo2.app.update.PropertyUpdate;
045: import nextapp.echo2.app.update.ServerComponentUpdate;
046: import nextapp.echo2.app.update.UpdateManager;
047: import junit.framework.TestCase;
048:
049: /**
050: * Unit test(s) for update management subsystem.
051: */
052: public class UpdateManagerTest extends TestCase {
053:
054: /**
055: * Test <code>Command</code>.
056: */
057: private static class ExampleCommand implements Command {
058: }
059:
060: /**
061: * Test <code>ApplicationInstance</code>.
062: */
063: private ColumnApp columnApp;
064:
065: /**
066: * <code>UpdateManager</code> for <code>columnApp</code>.
067: */
068: private UpdateManager manager;
069:
070: /**
071: * @see junit.framework.TestCase#setUp()
072: */
073: public void setUp() {
074: columnApp = new ColumnApp();
075: ApplicationInstance.setActive(columnApp);
076: columnApp.doInit();
077: manager = columnApp.getUpdateManager();
078: }
079:
080: /**
081: * @see junit.framework.TestCase#tearDown()
082: */
083: public void tearDown() {
084: ApplicationInstance.setActive(null);
085: }
086:
087: /**
088: * Test adding children to an parent that is being added in current
089: * transaction.
090: */
091: public void testAddChlidToAddedParent() {
092: ServerComponentUpdate[] componentUpdates;
093: Component[] addedChildren;
094: manager.purge();
095:
096: // Add a column.
097: Column column1 = new Column();
098: columnApp.getColumn().add(column1);
099:
100: // Ensure only 1 update w/ 1 child added.
101: componentUpdates = manager.getServerUpdateManager()
102: .getComponentUpdates();
103: assertEquals(1, componentUpdates.length);
104: addedChildren = componentUpdates[0].getAddedChildren();
105: assertEquals(1, addedChildren.length);
106: assertEquals(0, componentUpdates[0].getRemovedChildren().length);
107: assertEquals(column1, addedChildren[0]);
108:
109: // Add a label to column.
110: column1.add(new Label("A"));
111:
112: // Ensure only 1 update w/ 1 child added.
113: componentUpdates = manager.getServerUpdateManager()
114: .getComponentUpdates();
115: assertEquals(1, componentUpdates.length);
116: addedChildren = componentUpdates[0].getAddedChildren();
117: assertEquals(1, addedChildren.length);
118: assertEquals(0, componentUpdates[0].getRemovedChildren().length);
119: assertEquals(column1, addedChildren[0]);
120:
121: // Add another column.
122: Column column2 = new Column();
123: Label labelB = new Label("B");
124: column2.add(labelB);
125: columnApp.getColumn().add(column2);
126:
127: // Ensure only 1 update w/ 2 children added.
128: componentUpdates = manager.getServerUpdateManager()
129: .getComponentUpdates();
130: assertEquals(1, componentUpdates.length);
131: addedChildren = componentUpdates[0].getAddedChildren();
132: assertEquals(2, addedChildren.length);
133: assertEquals(0, componentUpdates[0].getRemovedChildren().length);
134:
135: List addedChildrenList = Arrays.asList(addedChildren);
136: assertTrue(addedChildrenList.contains(column1));
137: assertTrue(addedChildrenList.contains(column2));
138: assertFalse(addedChildrenList.contains(labelB));
139: }
140:
141: /**
142: * Ensure adding an invisible component does not add entries.
143: */
144: public void testAddInvisibleComponent() {
145: ServerComponentUpdate[] componentUpdates;
146:
147: manager.purge();
148:
149: Label label = new Label("Label1");
150: label.setVisible(false);
151: columnApp.getColumn().add(label);
152:
153: componentUpdates = manager.getServerUpdateManager()
154: .getComponentUpdates();
155: assertEquals(0, componentUpdates.length);
156: }
157:
158: /**
159: * Test storage/retrieval of application property update.
160: */
161: public void testApplicationPropertyUpdate() {
162: manager.purge();
163: columnApp.setFocusedComponent(columnApp.getLabel());
164: PropertyUpdate propertyUpdate = manager
165: .getServerUpdateManager()
166: .getApplicationPropertyUpdate(
167: ApplicationInstance.FOCUSED_COMPONENT_CHANGED_PROPERTY);
168: assertNotNull(propertyUpdate);
169: assertNull(propertyUpdate.getOldValue());
170: assertEquals(columnApp.getLabel(), propertyUpdate.getNewValue());
171: }
172:
173: /**
174: * Ensure that an application property update is stored in the
175: * <code>ServerUpdateManager</code> even if an update to the same
176: * property was received from the <code>ClientUpdateManager</code> BUT
177: * the property value is now different.
178: */
179: public void testApplicationPropertyUpdateWithDifferentClientUpdate() {
180: manager.purge();
181: manager.getClientUpdateManager().setApplicationProperty(
182: ApplicationInstance.FOCUSED_COMPONENT_CHANGED_PROPERTY,
183: columnApp.getColumn());
184: manager.processClientUpdates();
185: assertEquals(columnApp.getColumn(), columnApp
186: .getFocusedComponent());
187:
188: columnApp.setFocusedComponent(columnApp.getLabel());
189: PropertyUpdate propertyUpdate = manager
190: .getServerUpdateManager()
191: .getApplicationPropertyUpdate(
192: ApplicationInstance.FOCUSED_COMPONENT_CHANGED_PROPERTY);
193: assertNotNull(propertyUpdate);
194: assertEquals(columnApp.getColumn(), propertyUpdate
195: .getOldValue());
196: assertEquals(columnApp.getLabel(), propertyUpdate.getNewValue());
197: }
198:
199: /**
200: * Ensure that an application property update is NOT stored in the
201: * <code>ServerUpdateManager</code> as a result of a property update
202: * received from the <code>ClientUpdateManager</code>.
203: */
204: public void testApplicationPropertyUpdateWithEquivalentClientUpdate() {
205: manager.purge();
206: manager.getClientUpdateManager().setApplicationProperty(
207: ApplicationInstance.FOCUSED_COMPONENT_CHANGED_PROPERTY,
208: columnApp.getLabel());
209: manager.processClientUpdates();
210: assertEquals(columnApp.getLabel(), columnApp
211: .getFocusedComponent());
212: PropertyUpdate propertyUpdate = manager
213: .getServerUpdateManager()
214: .getApplicationPropertyUpdate(
215: ApplicationInstance.FOCUSED_COMPONENT_CHANGED_PROPERTY);
216: assertNull(propertyUpdate);
217: }
218:
219: /**
220: * Ensure property handling of <code>Command</code>s.
221: */
222: public void testCommand() {
223: Command command = new ExampleCommand();
224:
225: manager.purge();
226: columnApp.enqueueCommand(command);
227:
228: // Test basic command queuing.
229: assertEquals(1,
230: manager.getServerUpdateManager().getCommands().length);
231: assertEquals(command, manager.getServerUpdateManager()
232: .getCommands()[0]);
233:
234: manager.getServerUpdateManager().processFullRefresh();
235:
236: // Ensure command survives full refresh.
237: assertEquals(1,
238: manager.getServerUpdateManager().getCommands().length);
239: assertEquals(command, manager.getServerUpdateManager()
240: .getCommands()[0]);
241:
242: manager.purge();
243:
244: // Ensure command purged.
245: assertEquals(0,
246: manager.getServerUpdateManager().getCommands().length);
247:
248: manager.getServerUpdateManager().processFullRefresh();
249: columnApp.enqueueCommand(command);
250:
251: // Ensure commands can be enqueued even if a full refresh is present.
252: assertEquals(1,
253: manager.getServerUpdateManager().getCommands().length);
254: assertEquals(command, manager.getServerUpdateManager()
255: .getCommands()[0]);
256: }
257:
258: /**
259: * Ensure updates to invisible hierarchy do not add entries.
260: */
261: public void testInvisibleHierarchyUpdate() {
262: ServerComponentUpdate[] componentUpdates;
263: columnApp.getColumn().setVisible(false);
264:
265: manager.purge();
266:
267: Column column = new Column();
268: columnApp.getColumn().add(column);
269: Label label1 = new Label("Label1");
270: column.add(label1);
271: Label label2 = new Label("Label2");
272: label2.setVisible(false);
273: column.add(label2);
274:
275: componentUpdates = manager.getServerUpdateManager()
276: .getComponentUpdates();
277: assertEquals(0, componentUpdates.length);
278: }
279:
280: /**
281: * Test updating of <code>LayoutData</code> properties, ensuring that
282: * these properties correctly register updates for the
283: * <strong>parent</strong> <code>Component</code>.
284: */
285: public void testLayoutDataUpdate() {
286: ServerComponentUpdate[] componentUpdates;
287: ColumnLayoutData columnLayoutData;
288:
289: manager.purge();
290:
291: // Setup.
292: Column column = new Column();
293: columnApp.getColumn().add(column);
294: Label label1 = new Label("Label1");
295: column.add(label1);
296: Label label2 = new Label("Label2");
297: column.add(label2);
298: label2.setLayoutData(new ColumnLayoutData());
299:
300: componentUpdates = manager.getServerUpdateManager()
301: .getComponentUpdates();
302: assertEquals(1, componentUpdates.length);
303: assertEquals(false, componentUpdates[0]
304: .hasUpdatedLayoutDataChildren());
305:
306: manager.purge();
307:
308: columnLayoutData = new ColumnLayoutData();
309: columnLayoutData.setAlignment(new Alignment(Alignment.CENTER,
310: Alignment.DEFAULT));
311: label1.setLayoutData(columnLayoutData);
312: componentUpdates = manager.getServerUpdateManager()
313: .getComponentUpdates();
314: assertEquals(1, componentUpdates.length);
315: assertEquals(column, componentUpdates[0].getParent());
316: assertFalse(componentUpdates[0].hasAddedChildren());
317: assertFalse(componentUpdates[0].hasRemovedChildren());
318: assertFalse(componentUpdates[0].hasUpdatedProperties());
319: assertTrue(componentUpdates[0].hasUpdatedLayoutDataChildren());
320:
321: Component[] components = componentUpdates[0]
322: .getUpdatedLayoutDataChildren();
323: assertEquals(1, components.length);
324: assertEquals(label1, components[0]);
325: }
326:
327: /**
328: * Test recording of simple property updates, and their removal
329: * in the event that the updated <code>Component</code> is later
330: * removed.
331: */
332: public void testPropertyUpdate() {
333: ServerComponentUpdate[] componentUpdates;
334: // Remove previous updates.
335: manager.purge();
336:
337: // Update text property of label and verify.
338: columnApp.getLabel().setText("Hi there");
339: componentUpdates = manager.getServerUpdateManager()
340: .getComponentUpdates();
341: assertEquals(columnApp.getLabel(), componentUpdates[0]
342: .getParent());
343: assertEquals(1, componentUpdates.length);
344: assertEquals(0, componentUpdates[0].getAddedChildren().length);
345: assertEquals(0, componentUpdates[0].getRemovedChildren().length);
346:
347: String[] updatedPropertyNames = componentUpdates[0]
348: .getUpdatedPropertyNames();
349: assertEquals(1, updatedPropertyNames.length);
350: assertEquals(Label.PROPERTY_TEXT, updatedPropertyNames[0]);
351: PropertyUpdate propertyUpdate = componentUpdates[0]
352: .getUpdatedProperty(Label.PROPERTY_TEXT);
353: assertEquals("Label", propertyUpdate.getOldValue());
354: assertEquals("Hi there", propertyUpdate.getNewValue());
355:
356: // Remove label entirely and ensure property update disappears.
357: columnApp.getColumn().remove(columnApp.getLabel());
358: componentUpdates = manager.getServerUpdateManager()
359: .getComponentUpdates();
360: assertEquals(1, componentUpdates.length);
361: assertEquals(0,
362: componentUpdates[0].getUpdatedPropertyNames().length);
363: assertEquals(0, componentUpdates[0].getAddedChildren().length);
364: }
365:
366: /**
367: * Ensure that a property update whose state is already reflected on the
368: * client (because the end-user made the property change) is properly
369: * canceled.
370: */
371: public void testPropertyUpdateCancellation1() {
372: TextField textField = new TextField();
373: columnApp.getColumn().add(textField);
374:
375: manager.purge();
376: manager.getClientUpdateManager().setComponentProperty(
377: textField, TextField.TEXT_CHANGED_PROPERTY,
378: "a user typed this.");
379: manager.processClientUpdates();
380:
381: ServerComponentUpdate[] componentUpdates = manager
382: .getServerUpdateManager().getComponentUpdates();
383: assertEquals(0, componentUpdates.length);
384: }
385:
386: /**
387: * Ensure that a property update whose state is already reflected on the
388: * client (because the end-user made the property change) is properly
389: * canceled. This test will ensure that if additional properties changed
390: * on a user-updated component, that only the non-user-updated properties
391: * are reflected by the <code>UpdateManager</code>.
392: */
393: public void testPropertyUpdateCancellation2() {
394: TextField textField = new TextField();
395: columnApp.getColumn().add(textField);
396:
397: manager.purge();
398: textField.setBackground(Color.BLUE);
399: manager.getClientUpdateManager().setComponentProperty(
400: textField, TextField.TEXT_CHANGED_PROPERTY,
401: "a user typed this.");
402: manager.processClientUpdates();
403:
404: ServerComponentUpdate[] componentUpdates = manager
405: .getServerUpdateManager().getComponentUpdates();
406: assertEquals(1, componentUpdates.length);
407: PropertyUpdate backgroundUpdate = componentUpdates[0]
408: .getUpdatedProperty(TextField.PROPERTY_BACKGROUND);
409: assertNotNull(backgroundUpdate);
410: assertEquals(Color.BLUE, backgroundUpdate.getNewValue());
411: assertNull(componentUpdates[0]
412: .getUpdatedProperty(TextField.TEXT_CHANGED_PROPERTY));
413: }
414:
415: /**
416: * Ensure that a property update whose state is already reflected on the
417: * client (because the end-user made the property change) is properly
418: * canceled. This test will ensure that user-changed properties are
419: * canceled even in the event that the application ALSO updated the
420: * property, though it was later overwritten by a user update.
421: */
422: public void testPropertyUpdateCancellation3() {
423: TextField textField = new TextField();
424: columnApp.getColumn().add(textField);
425:
426: manager.purge();
427: textField.setText("first the application set it to this.");
428: manager.getClientUpdateManager().setComponentProperty(
429: textField, TextField.TEXT_CHANGED_PROPERTY,
430: "a user typed this.");
431: manager.processClientUpdates();
432:
433: ServerComponentUpdate[] componentUpdates = manager
434: .getServerUpdateManager().getComponentUpdates();
435: assertEquals(1, componentUpdates.length);
436: assertFalse(componentUpdates[0].hasUpdatedProperties());
437: }
438:
439: /**
440: * Test basic operation <code>UpdateManager.purge()</code> method.
441: */
442: public void testPurge() {
443: assertFalse(manager.getServerUpdateManager()
444: .getComponentUpdates().length == 0);
445: manager.purge();
446: assertTrue(manager.getServerUpdateManager()
447: .getComponentUpdates().length == 0);
448: }
449:
450: /**
451: * Ensure that component removes and descendant removes are properly stored.
452: */
453: public void testRemove1() {
454: Column column = new Column();
455: Label label = new Label();
456: column.add(label);
457: columnApp.getColumn().add(column);
458: manager.purge();
459:
460: columnApp.getColumn().remove(column);
461:
462: ServerComponentUpdate[] componentUpdates = manager
463: .getServerUpdateManager().getComponentUpdates();
464: assertEquals(1, componentUpdates.length);
465:
466: assertEquals(true, componentUpdates[0].hasRemovedChildren());
467: assertEquals(true, componentUpdates[0].hasRemovedDescendants());
468:
469: Component[] removedChildren = componentUpdates[0]
470: .getRemovedChildren();
471: assertEquals(1, removedChildren.length);
472: assertEquals(column, removedChildren[0]);
473:
474: Component[] removedDescendants = componentUpdates[0]
475: .getRemovedDescendants();
476: assertEquals(1, removedDescendants.length);
477: assertEquals(label, removedDescendants[0]);
478: }
479:
480: /**
481: * Another slightly more complex test to ensure that component
482: * removes/descendant removes are properly stored.
483: *
484: * -- Initial State --
485: * [ColumnApp]
486: * * Window
487: * * ContentPane
488: * * Column
489: * * Column1
490: * * Column2
491: * * label
492: *
493: * -- New State --
494: * [ColumnApp]
495: * * Window
496: * * ContentPane
497: * * Column
498: * * Column1 [REMOVED]
499: * X Column2 [REMOVED DESCENDANT]
500: * X label [REMOVED DESCENDANT]
501: */
502: public void testRemove2() {
503: Column column1 = new Column();
504: Column column2 = new Column();
505: column1.add(column2);
506: Label label = new Label();
507: column2.add(label);
508: columnApp.getColumn().add(column1);
509: manager.purge();
510:
511: column1.remove(column2);
512: columnApp.getColumn().remove(column1);
513:
514: ServerComponentUpdate[] componentUpdates = manager
515: .getServerUpdateManager().getComponentUpdates();
516: assertEquals(1, componentUpdates.length);
517:
518: assertEquals(true, componentUpdates[0].hasRemovedChildren());
519: assertEquals(true, componentUpdates[0].hasRemovedDescendants());
520:
521: Component[] removedChildren = componentUpdates[0]
522: .getRemovedChildren();
523: assertEquals(1, removedChildren.length);
524: assertEquals(column1, removedChildren[0]);
525:
526: Component[] removedDescendants = componentUpdates[0]
527: .getRemovedDescendants();
528: assertEquals(2, removedDescendants.length);
529: assertTrue(removedDescendants[0].equals(column2)
530: || removedDescendants[1].equals(column2));
531: assertTrue(removedDescendants[0].equals(label)
532: || removedDescendants[1].equals(label));
533: }
534:
535: /**
536: * Ensure updates are returned sorted by component depth.
537: */
538: public void testUpdateSorting1() {
539: ServerComponentUpdate[] componentUpdates;
540: manager.purge();
541:
542: columnApp.getLabel().setBackground(Color.BLUE);
543: columnApp.getContentPane().setBackground(Color.RED);
544: columnApp.getColumn().setBackground(Color.GREEN);
545: componentUpdates = manager.getServerUpdateManager()
546: .getComponentUpdates();
547:
548: assertEquals(3, componentUpdates.length);
549: assertEquals(columnApp.getContentPane(), componentUpdates[0]
550: .getParent());
551: assertEquals(columnApp.getColumn(), componentUpdates[1]
552: .getParent());
553: assertEquals(columnApp.getLabel(), componentUpdates[2]
554: .getParent());
555: }
556:
557: /**
558: * Ensure updates are returned sorted by component depth.
559: */
560: public void testUpdateSorting2() {
561: ServerComponentUpdate[] componentUpdates;
562: Column column2 = new Column();
563: columnApp.getColumn().add(column2);
564: Label label2 = new Label();
565: column2.add(label2);
566: manager.purge();
567:
568: columnApp.getLabel().setBackground(Color.BLUE);
569: columnApp.getContentPane().setBackground(Color.RED);
570: columnApp.getColumn().setBackground(Color.GREEN);
571: label2.setBackground(Color.YELLOW);
572: column2.setBackground(Color.ORANGE);
573:
574: componentUpdates = manager.getServerUpdateManager()
575: .getComponentUpdates();
576: assertEquals(5, componentUpdates.length);
577: assertEquals(columnApp.getContentPane(), componentUpdates[0]
578: .getParent());
579: assertEquals(columnApp.getColumn(), componentUpdates[1]
580: .getParent());
581: assertTrue(columnApp.getLabel().equals(
582: componentUpdates[2].getParent())
583: || columnApp.getLabel().equals(
584: componentUpdates[3].getParent()));
585: assertTrue(column2.equals(componentUpdates[2].getParent())
586: || column2.equals(componentUpdates[3].getParent()));
587: assertEquals(label2, componentUpdates[4].getParent());
588: }
589:
590: /**
591: * Ensure that visible updates are treated as adds/removes.
592: */
593: public void testVisibleUpdate() {
594: ServerComponentUpdate[] componentUpdates;
595:
596: manager.purge();
597:
598: // Setup.
599: Column column = new Column();
600: columnApp.getColumn().add(column);
601: Label label1 = new Label("Label1");
602: column.add(label1);
603: Label label2 = new Label("Label2");
604: label2.setVisible(false);
605: column.add(label2);
606: label2.setLayoutData(new ColumnLayoutData());
607:
608: manager.purge();
609:
610: label1.setVisible(false);
611: componentUpdates = manager.getServerUpdateManager()
612: .getComponentUpdates();
613: assertEquals(1, componentUpdates.length);
614: assertEquals(column, componentUpdates[0].getParent());
615: assertFalse(componentUpdates[0].hasAddedChildren());
616: assertTrue(componentUpdates[0].hasRemovedChildren());
617: assertFalse(componentUpdates[0].hasUpdatedProperties());
618: assertFalse(componentUpdates[0].hasUpdatedLayoutDataChildren());
619:
620: Component[] components = componentUpdates[0]
621: .getRemovedChildren();
622: assertEquals(1, components.length);
623: assertEquals(label1, components[0]);
624:
625: manager.purge();
626:
627: label2.setVisible(true);
628: componentUpdates = manager.getServerUpdateManager()
629: .getComponentUpdates();
630: assertEquals(1, componentUpdates.length);
631: assertEquals(column, componentUpdates[0].getParent());
632: assertTrue(componentUpdates[0].hasAddedChildren());
633: assertFalse(componentUpdates[0].hasRemovedChildren());
634: assertFalse(componentUpdates[0].hasUpdatedProperties());
635: assertFalse(componentUpdates[0].hasUpdatedLayoutDataChildren());
636:
637: components = componentUpdates[0].getAddedChildren();
638: assertEquals(1, components.length);
639: assertEquals(label2, components[0]);
640:
641: label1.setVisible(true);
642: }
643: }
|