/*
 * Copyright 2009 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.uibinder.test.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.ParagraphElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource.NotStrict;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.uibinder.test.client.EnumeratedLabel.Suffix;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DateLabel;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.NamedFrame;
import com.google.gwt.user.client.ui.NumberLabel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.StackPanel;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.ValueLabel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Functional test of UiBinder.
 */
public class UiBinderTest extends GWTTestCase {
  private WidgetBasedUi widgetUi;
  private DomBasedUi domUi;
  private com.google.gwt.user.client.ui.DockPanel root;

  @Override
  public String getModuleName() {
    return "com.google.gwt.uibinder.test.UiBinderSuite";
  }

  @Override
  public void gwtSetUp() throws Exception {
    super.gwtSetUp();
    UiBinderTestApp app = UiBinderTestApp.getInstance();
    widgetUi = app.getWidgetUi();
    domUi = app.getDomUi();
    root = widgetUi.root;
  }

  /**
   * Tests that the provided value takes precedence over a custom parser,
   * {@code UiFactory} or {@code UiConstructor}.
   * <p>
   * The fields are {@code final} and we test that they've correctly been
   * modified by the template.
   * 
   * @see http://code.google.com/p/google-web-toolkit/issues/detail?id=7740
   */
  public void testProvidedWidgetWithCustomInitializer() {
    // Custom parser: should use the provided header, as the one from the
    // template is passed to the (ignored) custom initializer. But the child
    // widget should have been set.
    assertEquals("Provided header text", widgetUi.myProvidedDisclosurePanel.getHeaderTextAccessor().getText());
    assertNotNull(widgetUi.myProvidedDisclosurePanelItem);
    assertSame(widgetUi.myProvidedDisclosurePanelItem, widgetUi.myProvidedDisclosurePanel.getContent());
    // UiConstructor
    assertEquals("ditto", widgetUi.providedAnnotatedStrictLabel.getText());
    // UiFactory
    assertEquals("from template", widgetUi.providedStrictLabel.getText());
  }

  public void testTableWithColumns() {
    assertEquals("col", domUi.narrowColumn.getTagName().toLowerCase());
    assertEquals("tr", domUi.tr.getTagName().toLowerCase());
    assertEquals("th", domUi.th1.getTagName().toLowerCase());
    assertEquals("th", domUi.th2.getTagName().toLowerCase());
  }

  public void testTableWithExplicitTbody() {
    assertEquals("tbody", domUi.tbody.getTagName().toLowerCase());
    assertEquals("th", domUi.th4.getTagName().toLowerCase());
  }

  public void testAutoboxingFieldRef() {
    FakeBundle fakeBundle = new FakeBundle();

    assertEquals(new Integer(fakeBundle.anInt()),
        widgetUi.primitiveIntoObject.getObjectInteger());
    assertEquals(fakeBundle.anIntegerObject().intValue(),
        widgetUi.objectIntoPrimitive.getRawInt());
    assertEquals(fakeBundle.anIntegerObject(),
        widgetUi.allObject.getObjectInteger());
    assertEquals(fakeBundle.anInt(), widgetUi.allPrimitive.getRawInt());

    assertEquals(new Integer((int) fakeBundle.aDouble()),
        widgetUi.mismatchPrimitiveIntoObject.getObjectInteger());
    assertEquals((int) fakeBundle.aDouble(),
        widgetUi.allMismatchPrimitive.getRawInt());

    assertEquals(new Boolean(fakeBundle.aBoolean()),
        widgetUi.primitiveBooleanIntoObject.getObjectBoolean());
    assertEquals(fakeBundle.aBooleanObject().booleanValue(),
        widgetUi.objectBooleanIntoPrimitive.getRawBoolean());
    assertEquals(fakeBundle.aBooleanObject(),
        widgetUi.allObjectBoolean.getObjectBoolean());
    assertEquals(fakeBundle.aBoolean(),
        widgetUi.allPrimitiveBoolean.getRawBoolean());
  }

  public void testAccessToNonStandardElement() {
    Element elm = widgetUi.nonStandardElement;
    assertEquals("I", elm.getTagName());
  }

  public void testAddStyleNamesAndDebugId() {
    Label l = widgetUi.lblDebugId;
    assertEquals("gwt-debug-joe", l.getElement().getId());

    assertEquals("styleName", l.getStylePrimaryName());

    WidgetBasedUiExternalResources resources = GWT.create(WidgetBasedUiExternalResources.class);
    assertTrue(l.getStyleName().contains("newStyle"));
    assertTrue(l.getStyleName().contains("anotherStyle"));
    assertTrue(l.getStyleName().contains("styleName-dependentStyle"));
    assertTrue(l.getStyleName().contains("styleName-anotherDependentStyle"));
    assertTrue(l.getStyleName().contains(
        "styleName-" + resources.style().prettyText()));
  }

  // TODO(rjrjr) The direction stuff in these tests really belongs in
  // DockPanelParserTest

  public void testAllowIdOnDomElements() {
    Element elm = DOM.getElementById("shouldSayHTML");
    assertEquals("HTML", elm.getInnerHTML());
  }

  public void testBraceEscaping() {
    assertEquals("blah di blah {foo: \"bar\"} di blah",
        widgetUi.bracedParagraph.getAttribute("fnord"));
  }

  public void testBundle() {
    assertEquals(getCenter(), widgetUi.bundledLabel.getParent());
    assertEquals(new FakeBundle().helloText(), widgetUi.bundledLabel.getText());
    WidgetBasedUiExternalResources resources = GWT.create(WidgetBasedUiExternalResources.class);
    assertEquals(resources.style().prettyText(),
        widgetUi.bundledLabel.getStyleName());

    Element pretty = DOM.getElementById("prettyPara");
    assertEquals(resources.style().prettyText(), pretty.getClassName());

    ArbitraryPojo pojo = new ArbitraryPojo();
    FooLabel foo = new FooLabel();
    foo.setPojo(pojo);
    assertEquals(foo.getText(), widgetUi.theFoo.getText());
  }

  public void testCenter() {
    // TODO(rjrjr) More of a test of HTMLPanelParser

    Widget center = getCenter();
    assertEquals(com.google.gwt.user.client.ui.DockPanel.CENTER,
        root.getWidgetDirection(center));
    assertEquals(HTMLPanel.class, center.getClass());
    String html = center.getElement().getInnerHTML();
    assertTrue(html.contains("main area"));
    assertTrue(html.contains("Button with"));
    assertTrue(html.contains("Of course"));

    assertEquals(center, widgetUi.myButton.getParent());
  }

  public void testComputedAttributeInPlaceholderedElement() {
    WidgetBasedUiExternalResources resources = GWT.create(WidgetBasedUiExternalResources.class);
    assertEquals(resources.style().prettyText(),
        widgetUi.spanInMsg.getClassName());
  }

  public void testComputedStyleInAPlaceholder() {
    WidgetBasedUiExternalResources resources = GWT.create(WidgetBasedUiExternalResources.class);
    assertEquals(resources.style().tmText(), widgetUi.tmElement.getClassName());
  }

  public void testCustomButtonBody() {
    assertEquals("Hi mom", widgetUi.toggle.getText());
  }

  public void testCustomDialogBox() {
    assertEquals("Custom dialog am I", widgetUi.fooDialog.getText());
    Widget body = widgetUi.fooDialog.iterator().next();
    assertTrue(body instanceof Label);
    assertEquals("body", ((Label) body).getText());
  }

  public void testDomAccessAndComputedAttributeOnPlaceholderedElement() {
    WidgetBasedUiExternalResources resources = GWT.create(WidgetBasedUiExternalResources.class);
    Element elem = DOM.getElementById("placeholdersSpan");
    assertEquals("bold", elem.getStyle().getProperty("fontWeight"));
    assertEquals(resources.style().prettyText(), elem.getClassName());
  }

  public void testDomAccessInHtml() {
    DivElement sideBar = widgetUi.sideBar;
    assertTrue("sideBar should start: \"This could\"",
        sideBar.getInnerText().startsWith("This could"));
    assertTrue("sideBar should end: \"example:\"",
        sideBar.getInnerText().endsWith("like that..."));
    assertEquals("Should have no id", "", sideBar.getAttribute("id"));
  }

  public void testDomAccessInHtmlPanel() {
    SpanElement messageInMain = widgetUi.messageInMain;
    String text = messageInMain.getInnerText().trim();
    assertTrue("sideBar should start: \"This is the main area\"",
        text.startsWith("This is the main area"));
    assertTrue("sideBar should end: \"example.\"", text.endsWith("example."));
  }

  public void testDomAttributeMessageWithFunnyChars() {
    ParagraphElement p = widgetUi.funnyCharsMessageDomAttributeParagraph;
    String t = p.getAttribute("title");
    assertEquals("funny characters \\ \" ' ' & < > > { }", t);
  }

  public void testDomAttributeNoMessageWithFunnyChars() {
    ParagraphElement p = widgetUi.funnyCharsDomAttributeParagraph;
    String t = p.getAttribute("title");
    assertEquals("funny characters \\ \" ' ' & < > > { }", t);
  }

  public void testDomTextMessageWithFunnyChars() {
    String t = widgetUi.funnyCharsMessageParagraph.getInnerText();
    assertEquals("They might show up in body text that has been marked for "
        + "translation: funny characters \\ \" \" ' ' & < > > { }", t);
  }

  public void testEmptyAttributesOkay() {
    assertEquals("", widgetUi.styleLess.getStyleName());
  }

  public void testMixOfWidgetsAndElementsInUiMsg() {
    assertEquals("single translatable message",
        widgetUi.mixedMessageWidget.getText());
    assertEquals("exciting and subtle",
        widgetUi.mixedMessageSpan.getInnerText());
  }

  public void testEnums() {
    Suffix expected = EnumeratedLabel.Suffix.tail;
    assertTrue("Should end with suffix \"" + expected + "\"",
        widgetUi.enumLabel.getText().endsWith(expected.toString()));
  }

  public void testCustomButtonParser() {
    // .toLowerCase normalization to keep IE happy
    assertEquals("<b>click me</b>",
        widgetUi.pushButton.getUpFace().getHTML().toLowerCase());
    assertTrue(widgetUi.pushButton.getUpHoveringFace().getHTML().contains(
        ">Click ME!<"));
    assertEquals("<b>click me!</b>",
        widgetUi.pushButton.getUpHoveringFace().getHTML().toLowerCase());
    // Can't test the images at all :-P
  }

  public void testProtectedDomTextMessageWithFunnyChars() {
    String t = widgetUi.funnyCharsProtectedMessageParagraph.getInnerText();
    assertEquals("Don't forget about protected untranslatable blocks: "
        + "funny characters \\ \" \" ' ' & < > > { }", t);
  }

  public void testDomTextInNamedElementMessageWithFunnyChars() {
    String t = widgetUi.funnyCharsMessageChildSpan.getInnerText();
    assertEquals("funny characters \\ \" \" ' ' & < > > { }", t);
  }

  public void suppressedForSafari3Fail_testDomTextNoMessageWithFunnyChars() {
    ParagraphElement p = widgetUi.funnyCharsParagraph;
    // WebKit does \n replace thing, so let's do it everywhere
    String t = p.getInnerHTML().replace("\n", " ").toLowerCase();
    String expected = "Templates can be marked up for <b>localization</b>, which presents alls "
        + "kinds of exciting opportunities for bugs related to character escaping. "
        + "Consider these funny characters \\ \" \" ' ' &amp; &lt; &gt; &gt; { }, and "
        + "the various places they might make your life miserable, like this "
        + "untranslated paragraph.";
    expected = expected.toLowerCase();
    assertEquals(expected, t);
  }

  public void testFieldAttribute() {
    assertEquals(getCenter(), widgetUi.gwtFieldLabel.getParent());
  }

  public void testFieldInPlaceholderedElement() {
    assertEquals("named portions", widgetUi.spanInMsg.getInnerText());
  }

  public void testGrid() {
    assertTrue(widgetUi.fooGrid.getWidget(0, 0) instanceof Label);
    assertTrue(widgetUi.fooGrid.getWidget(0, 1) instanceof Button);
    assertEquals(2, widgetUi.fooGrid.getColumnCount());
    assertEquals(1, widgetUi.fooGrid.getRowCount());
  }

  public void testListBox() {
    assertEquals(2, widgetUi.fooListBox.getItemCount());
    assertEquals("bar", widgetUi.fooListBox.getItemText(0));
    assertEquals("bar", widgetUi.fooListBox.getValue(0));
    assertEquals("bar 2", widgetUi.fooListBox.getItemText(1));
    assertEquals("bar2", widgetUi.fooListBox.getValue(1));
  }

  public void testMenuAttributes() {
    assertEquals(widgetUi.dropdownMenuBar.getStyleName(),
        widgetUi.myStyle.menuBar());
  }

  public void testMenuItems() {
    // Has a legacy MenuItemHTML in its midst
    assertEquals("The pig's in a hurry",
        widgetUi.menuItemLegacy.getElement().getInnerText());
    assertTrue("Style should include \"moppy\"",
        widgetUi.menuItemMop.getStyleName().contains("moppy"));
  }

  public void testMessageTrimming() {
    assertEquals("Title area, specified largely in HTML.",
        widgetUi.trimmedMessage.getInnerHTML());
    assertEquals("Tommy can you hear me? Can you field me near you?",
        widgetUi.gwtFieldLabel.getText());
  }

  public void testMinimalDom() {
    assertEquals("Expect no wrapper div around root", widgetUi.getElement(),
        root.getElement());
  }

  public void testNamedElementInAPlaceholder() {
    assertEquals("TM", widgetUi.tmElement.getInnerText());
  }

  public void testNestedBundle() {
    DomBasedUi.Resources resources = GWT.create(DomBasedUi.Resources.class);
    assertEquals(resources.style().bodyColor() + " "
        + resources.style().bodyFont(), domUi.root.getClassName());
  }

  interface Bundle extends ClientBundle {
    @Source(value = {"WidgetBasedUi.css", "Menu.css"})
    @NotStrict
    WidgetBasedUi.Style style();
  }

  public void testNoOverrideInheritedSharedCssClasses() {
    Bundle bundle = GWT.create(Bundle.class);
    String publicStyle = bundle.style().menuBar();
    String privateStyle = widgetUi.myStyle.menuBar();
    assertEquals(publicStyle, privateStyle);
  }

  public void suppressedForIEfail_testNonXmlEntities() {
    // This fragment includes both translated and non-translated strings
    ParagraphElement mainParagraph = widgetUi.main;
    final String innerHTML = mainParagraph.getInnerHTML().trim();
    assertTrue(innerHTML.contains(" \u261E \u2022 XHTML \u2022 \u261C"));
    assertTrue(innerHTML.startsWith("\u261E&nbsp;<span>"));
    assertTrue(innerHTML.endsWith("</span>&nbsp;\u261C"));
  }

  public void testNorth() {
    Widget north = root.getWidget(0);
    assertEquals(com.google.gwt.user.client.ui.DockPanel.NORTH,
        root.getWidgetDirection(north));
    assertEquals(HTML.class, north.getClass());
    assertTrue(((HTML) north).getHTML().contains("Title area"));
  }

  public void testPrivateStyleFromExternalCss() {
    ParagraphElement p = widgetUi.privateStyleParagraph;
    assertTrue("Some kind of class should be set",
        p.getClassName().length() > 0);
  }

  public void testPrivateStylesFromInlineCss() {
    ParagraphElement p = widgetUi.reallyPrivateStyleParagraph;
    assertTrue("Some kind of class should be set",
        p.getClassName().length() > 0);
    assertFalse("Should be a different style than privateStyleParagraph's",
        widgetUi.privateStyleParagraph.getClassName().equals(p.getClassName()));

    assertTrue("Some kind of class should be set",
        widgetUi.totallyPrivateStyleSpan.getClassName().length() > 0);
  }

  public void testRadioButton() {
    RadioButton able = widgetUi.myRadioAble;
    RadioButton baker = widgetUi.myRadioBaker;
    assertTrue("able should be checked", able.getValue());
    assertFalse("baker should not be checked", baker.getValue());
    assertEquals("radios", able.getName());
    assertEquals("radios", baker.getName());
  }

  public void testStackPanel() {
    StackPanel p = widgetUi.myStackPanel;
    assertNotNull("Panel exists", p);
    Widget w = widgetUi.myStackPanelItem;
    assertNotNull("Widget exists", w);
    boolean containsWidget = false;
    for (int i = 0; i < p.getWidgetCount(); i++) {
      if (p.getWidget(i) == w) {
        containsWidget = true;
      }
    }
    assertTrue("Panel contains widget", containsWidget);
  }

  public void testDisclosurePanel() {
    DisclosurePanel p = widgetUi.myDisclosurePanel;
    assertNotNull("Panel exists", p);
    Widget w = widgetUi.myDisclosurePanelItem;
    assertNotNull("Widget exists", w);
    assertEquals("Panel contains widget", w, p.getContent());
  }

  public void testAbsolutePanel() {
    AbsolutePanel p = widgetUi.myAbsolutePanel;
    assertNotNull("Panel exists", p);

    assertEquals("Panel contains exactly 3 widgets", 3, p.getWidgetCount());
    assertEquals("Panel contains expected itemA",
        widgetUi.myAbsolutePanelItemA, p.getWidget(0));
    assertEquals("Panel contains expected itemB",
        widgetUi.myAbsolutePanelItemB, p.getWidget(1));
    assertEquals("Panel contains expected itemC",
        widgetUi.myAbsolutePanelItemC, p.getWidget(2));

    /*
     * The following fails on Safari 3, off by a few pixels. The coverage in
     * AbsolutePanelParserTest and AbsolutePanelTest are enough to make up for
     * the lack. Leaving this here as a warning to the next guy.
     */
    // {
    // Widget w = widgetUi.myAbsolutePanelItemA;
    // assertNotNull("Widget exists", w);
    // assertEquals("Widget has left", 1, p.getWidgetLeft(w));
    // assertEquals("Widget has top", 2, p.getWidgetTop(w));
    // }
    //
    // {
    // Widget w = widgetUi.myAbsolutePanelItemC;
    // assertNotNull("Widget exists", w);
    // assertEquals("Widget has left", 10, p.getWidgetLeft(w));
    // assertEquals("Widget has top", 20, p.getWidgetTop(w));
    // }
  }
  
  public void testNamedFrame() {
    NamedFrame p = widgetUi.myNamedFrame;
    assertNotNull("NamedFrame exists", p);
  }
  
  public void testTree() {
    Tree tree = widgetUi.myTree;
    TreeItem complexItem = widgetUi.myTreeItemC;
    // top level items
    assertEquals(3, tree.getItemCount());
    assertSame(widgetUi.myTreeItemA, tree.getItem(0));
    assertSame(widgetUi.myTreeWidgetB, tree.getItem(1).getWidget());
    assertSame(complexItem, tree.getItem(2));
    // complex item
    assertSame(2, complexItem.getChildCount());
    assertSame(widgetUi.myTreeItemCA, complexItem.getChild(0));
    assertSame(widgetUi.myTreeWidgetCB, complexItem.getChild(1).getWidget());
  }

  public void testDateLabel() {
    DateLabel p = widgetUi.myDateLabel;
    assertNotNull("DateLabel exists", p);
    p = widgetUi.myDateLabel2;
    assertNotNull("DateLabel exists", p);
    p = widgetUi.myDateLabel3;
    assertNotNull("DateLabel exists", p);
  }

  public void testNumberLabel() {
    NumberLabel<Float> p = widgetUi.myNumberLabel;
    assertNotNull("NumberLabel exists", p);
  }

  public void testValueLabel() {
    ValueLabel<Double> p = widgetUi.myValueLabel;
    assertNotNull("ValueLabel exists", p);
  }

  public void testStringAttributeIgnoresStaticSetter() {
    // Assumes setPopupText() is overloaded such that there is a static
    // setPopupText(Foo, String) method.
    ClickyLink clicky = widgetUi.customLinkWidget;
    assertEquals("overloaded setter should have been called", "That tickles!",
        clicky.getPopupText());
  }

  public void testStringAttributeWithFormatChars() {
    assertEquals("100%", root.getElement().getStyle().getProperty("width"));
  }

  public void testWest() {
    Widget west = root.getWidget(1);
    assertEquals(com.google.gwt.user.client.ui.DockPanel.WEST,
        root.getWidgetDirection(west));
    assertEquals(HTML.class, west.getClass());
    String html = ((HTML) west).getHTML();
    assertTrue(html.contains("side bar"));
  }

  public void testWidgetAttributeMessageWithFunnyChars() {
    ClickyLink clicky = widgetUi.funnyCharsMessageAttributeWidget;
    String t = clicky.getPopupText();
    assertEquals("funny characters \\ \" ' ' & < > > { }", t);
  }

  public void testWidgetAttributeNoMessageWithFunnyChars() {
    ClickyLink clicky = widgetUi.funnyCharsAttributeWidget;
    String t = clicky.getPopupText();
    assertEquals("funny characters \\ \" ' ' & < > > { }", t);
  }

  /**
   * Fails in all modes due to an HtmlUnit bug: offsetWidth always returns 1256.
   * TODO(t.broyer): file a new HtmlUnit bug.
   * Similar to http://sourceforge.net/p/htmlunit/bugs/1447/
   */
  @DoNotRunWith(Platform.HtmlUnitBug)
  public void testCustomImageClass() {
    ImageResource resource = widgetUi.prettyImage;
    Image widget = widgetUi.fooImage;
    assertEquals(resource.getWidth(), widget.getOffsetWidth());
    assertEquals(resource.getHeight(), widget.getOffsetHeight());
    assertEquals(resource.getTop(), widget.getOriginTop());
    assertEquals(resource.getLeft(), widget.getOriginLeft());
  }

  /**
   * Fails in all modes due to an HtmlUnit bug: offsetWidth always returns 1256.
   * TODO(t.broyer): file a new HtmlUnit bug.
   * Similar to http://sourceforge.net/p/htmlunit/bugs/1447/
   */
  @DoNotRunWith(Platform.HtmlUnitBug)
  public void testImageResourceInImageWidget() {
    ImageResource resource = widgetUi.prettyImage;
    Image widget = widgetUi.babyWidget;
    assertEquals(resource.getWidth(), widget.getOffsetWidth());
    assertEquals(resource.getHeight(), widget.getOffsetHeight());
    assertEquals(resource.getTop(), widget.getOriginTop());
    assertEquals(resource.getLeft(), widget.getOriginLeft());

    assertEquals("expected alt text", widget.getAltText());
    assertEquals("expected style name", widget.getStyleName());
  }

  public void testIntPair() {
    assertEquals(100, widgetUi.sideBarWidget.getOffsetWidth());
    assertEquals(150, widgetUi.sideBarWidget.getOffsetHeight());
  }

  public void testDataResource() {
    assertNotNull(widgetUi.heartCursorResource.getSafeUri());
  }

  public void testCssImportedScopes() {
    assertEquals(100, widgetUi.cssImportScopeSample.inner.getOffsetWidth());
  }

  public void testSpritedElement() {
    assertEquals(widgetUi.prettyImage.getWidth(),
        widgetUi.simpleSpriteParagraph.getOffsetWidth());
    assertEquals(widgetUi.prettyImage.getHeight(),
        widgetUi.simpleSpriteParagraph.getOffsetHeight());
  }

  public void testStaticImport() {
    assertEquals(Constants.CONST_FOO,
        widgetUi.bracedParagraph.getAttribute("foo"));
    assertEquals(Constants.Inner.CONST_BAR + " " + Constants.Inner.CONST_BAZ,
        widgetUi.bracedParagraph.getAttribute("bar"));
    assertEquals(Constants.MyEnum.ENUM_1.name() + " "
        + Constants.MyEnum.ENUM_2.name(),
        widgetUi.bracedParagraph.getAttribute("enum"));
  }

  public void suppressForIEfail_testBizarrelyElementedWidgets() {
    assertInOrder(widgetUi.widgetCrazyTable.getInnerHTML().toLowerCase(),
        "<td>they have been known</td>", "<td>to write widgets</td>",
        "<td>that masquerade</td>", "<td>as table cells,</td>",
        "<td>just like these.</td>", "<td>burma shave</td>");

    assertInOrder(widgetUi.widgetCrazyOrderedList.getInnerHTML(),
        "<li>similar</li>", "<li>things</li>");

    assertInOrder(widgetUi.widgetCrazyDefinitionList.getInnerHTML(),
        "<dt>Being</dt>", "<dd>done</dd>", "<dd>with</dd>", "<dd>lists</dd>");
  }

  public void testCustomHtmlPanelTag() {
    assertInOrder(widgetUi.customTagHtmlPanel.getElement().getInnerHTML(),
        "<td>Even HTMLPanel gets in on the game</td>",
        "<td>Lately, anyway.</td>");
  }

  public void testAlignmentAttributes() {
    assertEquals("left",
      widgetUi.myHorizontalPanel.getHorizontalAlignment().getTextAlignString());
    assertEquals("middle",
      widgetUi.myHorizontalPanel.getVerticalAlignment().getVerticalAlignString());

    final String innerHtml = 
      widgetUi.myHorizontalPanel.getElement().getInnerHTML();
    assertInOrder(innerHtml, "vertical-align: middle",
        "a stackpanel");
    
    final String innerHtml2 = innerHtml.replace("\"", "");
    assertInOrder(innerHtml2, "align=left", "a stackpanel");
  }
  
  public void testUrlResource() {
    assertEquals(new FakeBundle().aUrl(), widgetUi.myImage.getSrc());
  }
  
  public void testUiTextWithSafeHtml() {
    assertEquals("<b>this text should be bold!</b>",
        widgetUi.htmlWithComputedSafeHtml.getHTML().toLowerCase());
    assertEquals("&lt;b&gt;this text won't be bold!&lt;/b&gt;",
        widgetUi.htmlWithComputedText.getHTML().toLowerCase().replaceAll(">", "&gt;"));
    assertEquals("<b>this text won't be bold!</b>",
        widgetUi.labelWithComputedText.getText().toLowerCase());
  }
  
  /**
   * Assert that the expect strings are found in body, and in the order given.
   * WARNING: both body and expected are normalized to lower case, to get around
   * IE's habit of returning capitalized DOM elements.
   */
  private void assertInOrder(String body, String... expected) {
    body = body.toLowerCase();
    int lastIndex = 0;
    String lastExpected = "";

    for (String next : expected) {
      next = next.toLowerCase();
      int index = body.indexOf(next);
      assertTrue(body + " should contain " + next, index > -1);
      assertTrue("Expect " + next + " after " + lastExpected, index > lastIndex);
      lastIndex = index;
    }
  }

  private Widget getCenter() {
    Widget center = root.getWidget(2);
    return center;
  }
}
