001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.client.ui;
017:
018: import com.google.gwt.user.client.DOM;
019:
020: import junit.framework.Assert;
021:
022: /**
023: * All Widgets that implement HasWidgets should derive from this test case, and
024: * make sure to run all of its test templates.
025: */
026: public abstract class HasWidgetsTester {
027:
028: /**
029: * Used in test templates to allow the child class to specify how a widget
030: * will be added to its container. This is necessary because
031: * {@link HasWidgets#add(Widget)} is allowed to throw
032: * {@link UnsupportedOperationException}.
033: */
034: interface WidgetAdder {
035:
036: /**
037: * Adds the specified child to a container.
038: */
039: void addChild(HasWidgets container, Widget child);
040: }
041:
042: /**
043: * Default implementation used by containers for which
044: * {@link HasWidgets#add(Widget)} will not throw an exception.
045: */
046: private static class DefaultWidgetAdder implements WidgetAdder {
047: public void addChild(HasWidgets container, Widget child) {
048: container.add(child);
049: }
050: }
051:
052: private static class TestWidget extends Widget {
053: TestWidget() {
054: setElement(DOM.createDiv());
055: }
056:
057: protected void onLoad() {
058: // During onLoad, isAttached must be true, and the element be a descendant
059: // of the body element.
060: Assert.assertTrue(isAttached());
061: Assert.assertTrue(DOM.isOrHasChild(RootPanel
062: .getBodyElement(), getElement()));
063: }
064:
065: protected void onUnload() {
066: // During onUnload, everything must *still* be attached.
067: Assert.assertTrue(isAttached());
068: Assert.assertTrue(DOM.isOrHasChild(RootPanel
069: .getBodyElement(), getElement()));
070: }
071: }
072:
073: /**
074: * Runs all tests for {@link HasWidgets}. It is recommended that tests call
075: * this method or {@link #testAll(HasWidgets, WidgetAdder} so that future
076: * tests are automatically included.
077: *
078: * @param container
079: */
080: static void testAll(HasWidgets container) {
081: testAll(container, new DefaultWidgetAdder());
082: }
083:
084: /**
085: * Runs all tests for {@link HasWidgets}. It is recommended that tests call
086: * this method or {@link #testAll(HasWidgets, WidgetAdder)} so that future
087: * tests are automatically included.
088: *
089: * @param container
090: * @param adder
091: */
092: static void testAll(HasWidgets container, WidgetAdder adder) {
093: testAttachDetachOrder(container, adder);
094: testRemovalOfNonExistantChild(container);
095: }
096:
097: /**
098: * Tests attach and detach order, assuming that the container's
099: * {@link HasWidgets#add(Widget)} method does not throw
100: * {@link UnsupportedOperationException}.
101: *
102: * @param test
103: * @param container
104: * @see #testAttachDetachOrder(TestCase, HasWidgets,
105: * com.google.gwt.user.client.ui.HasWidgetsTester.WidgetAdder)
106: */
107: static void testAttachDetachOrder(HasWidgets container) {
108: testAttachDetachOrder(container, new DefaultWidgetAdder());
109: }
110:
111: /**
112: * Ensures that children are attached and detached in the proper order. This
113: * must result in the child's onLoad() method being called just *after* its
114: * element is attached to the DOM, and its onUnload method being called just
115: * *before* its element is detached from the DOM.
116: */
117: static void testAttachDetachOrder(HasWidgets container,
118: WidgetAdder adder) {
119: // Make sure the container's attached.
120: Assert.assertTrue(container instanceof Widget);
121: RootPanel.get().add((Widget) container);
122:
123: // Adding and removing the test widget will cause it to test onLoad and
124: // onUnload order.
125: TestWidget widget = new TestWidget();
126: adder.addChild(container, widget);
127: container.remove(widget);
128:
129: // After removal, the widget should be detached.
130: Assert.assertFalse(widget.isAttached());
131: Assert.assertFalse(DOM.isOrHasChild(RootPanel.getBodyElement(),
132: widget.getElement()));
133: }
134:
135: /**
136: * Tests to ensure that {@link HasWidgets#remove(Widget)} is resilient to
137: * being called with a widget that is not present as a child in the container.
138: *
139: * @param container
140: */
141: static void testRemovalOfNonExistantChild(HasWidgets container) {
142: TestWidget widget = new TestWidget();
143: container.remove(widget);
144: }
145: }
|