| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.cell.client; |
| |
| import com.google.gwt.cell.client.Cell.Context; |
| import com.google.gwt.dom.client.Document; |
| import com.google.gwt.dom.client.Element; |
| import com.google.gwt.dom.client.NativeEvent; |
| import com.google.gwt.junit.client.GWTTestCase; |
| import com.google.gwt.safehtml.shared.SafeHtmlBuilder; |
| import com.google.gwt.user.client.DOM; |
| import com.google.gwt.user.client.Event; |
| import com.google.gwt.user.client.EventListener; |
| |
| import java.util.Set; |
| |
| /** |
| * Base class for testing {@link Cell}. |
| * |
| * @param <T> the cell type |
| */ |
| public abstract class CellTestBase<T> extends GWTTestCase { |
| |
| /** |
| * A mock cell used for testing. |
| * |
| * @param <T> the cell type |
| */ |
| static class MockCell<T> extends AbstractCell<T> { |
| |
| private final boolean isSelectable; |
| private Context lastContext; |
| private T lastEventValue; |
| private Element lastParentElement; |
| private final T updateValue; |
| |
| public MockCell(boolean isSelectable, T updateValue, |
| String... consumedEvents) { |
| super(consumedEvents); |
| this.isSelectable = isSelectable; |
| this.updateValue = updateValue; |
| } |
| |
| public void assertLastEventValue(T expected) { |
| assertEquals(expected, lastEventValue); |
| } |
| |
| public void assertLastParentElement(Element expected) { |
| assertEquals(expected, lastParentElement); |
| } |
| |
| @Override |
| public boolean dependsOnSelection() { |
| return isSelectable; |
| } |
| |
| public Context getLastContext() { |
| return lastContext; |
| } |
| |
| @Override |
| public boolean handlesSelection() { |
| return isSelectable; |
| } |
| |
| @Override |
| public void onBrowserEvent(Context context, Element parent, T value, |
| NativeEvent event, ValueUpdater<T> valueUpdater) { |
| lastContext = context; |
| lastParentElement = parent; |
| lastEventValue = value; |
| if (valueUpdater != null) { |
| valueUpdater.update(updateValue); |
| } |
| } |
| |
| @Override |
| public void render(Context context, T value, SafeHtmlBuilder sb) { |
| lastContext = context; |
| if (value != null) { |
| sb.appendEscaped(String.valueOf(value)); |
| } |
| } |
| } |
| |
| /** |
| * A mock {@link ValueUpdater} used for testing. |
| */ |
| class MockValueUpdater implements ValueUpdater<T> { |
| |
| private T lastValue; |
| |
| public void assertLastValue(T expected) { |
| assertEquals(expected, lastValue); |
| lastValue = null; |
| } |
| |
| @Override |
| public void update(T value) { |
| assertNull(lastValue); |
| assertNotNull(value); |
| this.lastValue = value; |
| } |
| } |
| |
| /** |
| * The default row value key used for all tests. |
| */ |
| protected static final Object DEFAULT_KEY = new Object(); |
| |
| @Override |
| public String getModuleName() { |
| return "com.google.gwt.cell.CellTest"; |
| } |
| |
| public void testDependsOnSelection() { |
| assertEquals(dependsOnSelection(), createCell().dependsOnSelection()); |
| } |
| |
| public void testGetConsumedEvents() { |
| Set<String> consumedEvents = createCell().getConsumedEvents(); |
| String[] expected = getConsumedEvents(); |
| if (consumedEvents == null && expected == null) { |
| return; |
| } |
| assertEquals(expected.length, consumedEvents.size()); |
| for (String typeName : expected) { |
| assertTrue(consumedEvents.contains(typeName)); |
| } |
| } |
| |
| public void testHandlesSelection() { |
| // None of the provided cells handle selection. |
| assertFalse(createCell().handlesSelection()); |
| } |
| |
| /** |
| * Test rendering the cell with a valid value and no view data. |
| */ |
| public void testRender() { |
| Cell<T> cell = createCell(); |
| T value = createCellValue(); |
| SafeHtmlBuilder sb = new SafeHtmlBuilder(); |
| Context context = new Context(0, 0, null); |
| cell.render(context, value, sb); |
| assertEquals(getExpectedInnerHtml(), sb.toSafeHtml().asString()); |
| } |
| |
| /** |
| * Test rendering the cell with a negative index is handled. |
| */ |
| public void testRenderNegativeIndex() { |
| Cell<T> cell = createCell(); |
| T value = createCellValue(); |
| SafeHtmlBuilder sb = new SafeHtmlBuilder(); |
| Context context = new Context(-1, -1, null); |
| cell.render(context, value, sb); |
| assertEquals(getExpectedInnerHtml(), sb.toSafeHtml().asString()); |
| } |
| |
| /** |
| * Test rendering the cell with a null value and no view data. |
| */ |
| public void testRenderNull() { |
| Cell<T> cell = createCell(); |
| SafeHtmlBuilder sb = new SafeHtmlBuilder(); |
| Context context = new Context(0, 0, null); |
| cell.render(context, null, sb); |
| assertEquals(getExpectedInnerHtmlNull(), sb.toSafeHtml().asString()); |
| } |
| |
| /** |
| * Create a new cell to test. |
| * |
| * @return the new cell |
| */ |
| protected abstract Cell<T> createCell(); |
| |
| /** |
| * Create a value to test. |
| * |
| * @return the cell value |
| */ |
| protected abstract T createCellValue(); |
| |
| /** |
| * Does the cell type depend on selection? Default to false. |
| * |
| * @return true expected value of dependsOnSelection |
| */ |
| protected abstract boolean dependsOnSelection(); |
| |
| /** |
| * Get the expected events that the cell should consume. |
| * |
| * @return the consumed events. |
| */ |
| protected abstract String[] getConsumedEvents(); |
| |
| /** |
| * Get the expected inner HTML value of the rendered cell. |
| * |
| * @return the expected string |
| */ |
| protected abstract String getExpectedInnerHtml(); |
| |
| /** |
| * Get the expected inner HTML value of the rendered cell when null is passed |
| * as the cell value. |
| * |
| * @return the expected string |
| */ |
| protected abstract String getExpectedInnerHtmlNull(); |
| |
| /** |
| * Test |
| * {@link Cell#onBrowserEvent(Element, Object, Object, NativeEvent, ValueUpdater)} |
| * with the specified conditions. |
| * |
| * @param startHtml the innerHTML of the cell before the test starts |
| * @param event the event to fire |
| * @param value the cell value |
| * @param expectedValue the expected value passed to the value updater, or |
| * null if none expected |
| * @return the parent element |
| */ |
| protected Element testOnBrowserEvent(String startHtml, NativeEvent event, final T value, |
| T expectedValue) { |
| return testOnBrowserEvent(createCell(), startHtml, event, value, expectedValue, true); |
| } |
| |
| /** |
| * Test |
| * {@link Cell#onBrowserEvent(Element, Object, Object, NativeEvent, ValueUpdater)} |
| * with the specified conditions. |
| * |
| * @param cell the cell to use |
| * @param startHtml the innerHTML of the cell before the test starts |
| * @param event the event to fire |
| * @param value the cell value |
| * @param expectedValue the expected value passed to the value updater, or |
| * null if none expected |
| * @param dispatchToFirstChild true to dispatch to the first child of the |
| * rendered parent element, if one is available |
| * @return the parent element |
| */ |
| protected Element testOnBrowserEvent(final Cell<T> cell, String startHtml, NativeEvent event, |
| final T value, T expectedValue, boolean dispatchToFirstChild) { |
| // Setup the parent element. |
| final Element parent = Document.get().createDivElement(); |
| parent.setInnerHTML(startHtml); |
| Document.get().getBody().appendChild(parent); |
| |
| // If the element has a child, use it as the event target. |
| Element target = parent; |
| if (dispatchToFirstChild) { |
| Element child = parent.getFirstChildElement(); |
| target = (child == null) ? parent : child; |
| } |
| |
| // Pass the event to the cell. |
| final MockValueUpdater valueUpdater = new MockValueUpdater(); |
| Event.setEventListener(parent, new EventListener() { |
| @Override |
| public void onBrowserEvent(Event event) { |
| try { |
| DOM.setEventListener(parent, null); |
| Context context = new Context(0, 0, DEFAULT_KEY); |
| cell.onBrowserEvent(context, parent, value, event, valueUpdater); |
| parent.removeFromParent(); |
| } catch (Exception e) { |
| // We are in an event loop, so events may not propagate out to JUnit. |
| fail("An exception occured while handling the event: " + e.getMessage()); |
| } |
| } |
| }); |
| Event.sinkEvents(target, Event.getTypeInt(event.getType())); |
| target.dispatchEvent(event); |
| assertNull(DOM.getEventListener(parent)); |
| |
| // Check the expected value and view data. |
| valueUpdater.assertLastValue(expectedValue); |
| return parent; |
| } |
| } |