/* * 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.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; } 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 \\ \" \" ' ' & < > > { }, 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 <span>")); assertTrue(innerHTML.endsWith("</span> \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); } 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()); } 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("<b>this text won't be bold!</b>", widgetUi.htmlWithComputedText.getHTML().toLowerCase().replaceAll(">", ">")); 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; } }