blob: 10d1e8a7110827c37682ff591c34b3c4c1704aa7 [file] [log] [blame]
/*
* Copyright 2008 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.user.client;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.http.client.URL;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.Window.Navigator;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Test Case for {@link Window}.
*/
public class WindowTest extends GWTTestCase {
private static native String getNodeName(Element elem) /*-{
return (elem.nodeName || "").toLowerCase();
}-*/;
/**
* Removes all elements in the body, except scripts and iframes.
*/
private static void clearBodyContent() {
Element bodyElem = RootPanel.getBodyElement();
List<Element> toRemove = new ArrayList<Element>();
for (int i = 0, n = DOM.getChildCount(bodyElem); i < n; ++i) {
Element elem = DOM.getChild(bodyElem, i);
String nodeName = getNodeName(elem);
if (!"script".equals(nodeName) && !"iframe".equals(nodeName)) {
toRemove.add(elem);
}
}
for (int i = 0, n = toRemove.size(); i < n; ++i) {
DOM.removeChild(bodyElem, toRemove.get(i));
}
}
@Override
public String getModuleName() {
return "com.google.gwt.user.User";
}
public void testLocation() {
// testing reload, replace, and assign seemed to hang our junit harness.
// Therefore only testing subset of Location that is testable.
// Use History to get the #hash part of the url into a known state (if the
// url has somehow been set to http://host/#, location.hash returns the
// empty string, but location.href includes the trailing hash).
History.newItem("foo bar");
// As we have no control over these values we cannot assert much about them.
String hash = Window.Location.getHash();
String host = Window.Location.getHost();
String hostName = Window.Location.getHostName();
String href = Window.Location.getHref();
assertNull(Window.Location.getParameter("fuzzy bunny"));
String path = Window.Location.getPath();
String port = Window.Location.getPort();
String protocol = Window.Location.getProtocol();
String query = Window.Location.getQueryString();
// Check that the sum is equal to its parts.
assertEquals(host, hostName + ":" + port);
assertEquals(href, protocol + "//" + host + path + query + hash);
}
public void testLocationCreateUrlBuilder() {
History.newItem("theHash");
String expected = Location.getHref();
// Build the string with the builder.
UrlBuilder builder = Location.createUrlBuilder();
String actual = builder.buildString();
// Check the hash.
{
String[] expectedParts = expected.split("#");
String[] actualParts = actual.split("#");
assertEquals(2, actualParts.length);
assertEquals(expectedParts[1], actualParts[1]);
expected = expectedParts[0];
actual = actualParts[0];
}
// Check the query parameters.
{
String[] expectedParts = expected.split("[?]");
String[] actualParts = actual.split("[?]");
if (expectedParts.length > 1) {
assertEquals(2, actualParts.length);
String[] expectedPairs = expectedParts[1].split("&");
String[] actualPairs = actualParts[1].split("&");
assertEquals(expectedPairs.length, actualPairs.length);
for (String actualPair : actualPairs) {
String[] kv = actualPair.split("=");
assertEquals(Location.getParameter(kv[0]),
// has a URL encoded ':' in a parameter
kv.length > 1 ? URL.decodeQueryString(kv[1]) : "");
}
}
expected = expectedParts[0];
actual = actualParts[0];
}
// Check everything but the query params and hash/
assertEquals(expected, actual);
}
public void testLocationParsing() {
Map<String, List<String>> map;
// typical case
map = Window.Location.buildListParamMap("?fuzzy=bunnies&foo=bar&num=42");
assertEquals(map.size(), 3);
assertEquals(map.get("foo").get(0), "bar");
assertEquals(map.get("fuzzy").get(0), "bunnies");
// multiple values for the same parameter
map = Window.Location.buildListParamMap(
"?fuzzy=bunnies&foo=bar&num=42&foo=baz");
assertEquals(map.size(), 3);
assertEquals(map.get("foo").get(0), "bar");
assertEquals(map.get("foo").get(1), "baz");
// no query parameters.
map = Window.Location.buildListParamMap("");
assertEquals(map.size(), 0);
// blank keys should be ignored, but blank values are OK. Also,
// keys can contain whitespace. (but the browser may give whitespace
// back as escaped).
map = Window.Location.buildListParamMap("?&& &a&b=&c=c&d=d=d&=e&f=2&f=1&");
assertEquals(map.size(), 6);
assertEquals(map.get(" ").get(0), "");
assertEquals(map.get("a").get(0), "");
assertEquals(map.get("b").get(0), "");
assertEquals(map.get("c").get(0), "c");
assertEquals(map.get("d").get(0), "d=d");
assertEquals(map.get("f").get(0), "2");
assertEquals(map.get("f").get(1), "1");
// Values escaped with hex codes should work too.
map = Window.Location.buildListParamMap("?foo=bar%20baz%3aqux");
assertEquals(map.get("foo").get(0), "bar baz:qux");
}
public void testNavigator() {
assertNotNull(Navigator.getAppCodeName());
assertNotNull(Navigator.getAppName());
assertNotNull(Navigator.getAppVersion());
assertNotNull(Navigator.getPlatform());
assertNotNull(Navigator.getUserAgent());
assertTrue(Navigator.isCookieEnabled());
// We don't care if Java is enabled, but need to make sure this call does
// not throw. The try/catch block keeps the compiled code from being
// optimized away.
try {
Navigator.isJavaEnabled();
} catch (JavaScriptException e) {
throw e;
}
}
/**
* Tests the ability of the Window to get the client size correctly with and
* without visible scroll bars.
* Failed in all modes due to HtmlUnit bug:
* https://sourceforge.net/tracker/?func=detail&aid=2944261&group_id=47038&atid=448266
*/
@DoNotRunWith(Platform.HtmlUnitBug)
public void testGetClientSize() {
// NOTE: We must clear the DOM here so that previous tests do not pollute
// our results.
clearBodyContent();
// Get the dimensions without any scroll bars
Window.enableScrolling(false);
final int oldClientHeight = Window.getClientHeight();
final int oldClientWidth = Window.getClientWidth();
assertTrue("Expect positive oldClientHeight. "
+ "This will fail in WebKit if run headless", oldClientHeight > 0);
assertTrue(oldClientWidth > 0);
// Firefox hides scrollbar if clientHeight < 49 even when it should show.
// If we are in this case, simply return.
if (oldClientHeight < 49 && Navigator.getUserAgent().contains("Firefox")) {
return;
}
// Compare to the dimensions with scroll bars
Window.enableScrolling(true);
final Label largeDOM = new Label();
largeDOM.setPixelSize(oldClientWidth + 100, oldClientHeight + 100);
RootPanel.get().add(largeDOM);
delayTestFinish(1000);
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
int newClientHeight = Window.getClientHeight();
int newClientWidth = Window.getClientWidth();
assertTrue(newClientHeight < oldClientHeight);
assertTrue(newClientWidth < oldClientWidth);
RootPanel.get().remove(largeDOM);
finishTest();
}
});
}
private static final class TestResizeHandler implements ResizeHandler {
private int height;
private int width;
private boolean called;
public void onResize(ResizeEvent event) {
width = event.getWidth();
height = event.getHeight();
called = true;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public boolean isCalled() {
return called;
}
}
/**
* Tests the ability of resize the Window and catch resize events.
*/
@DoNotRunWith({Platform.HtmlUnitLayout})
public void testResizing() {
// There is nothing to test if the browser doesn't support resize
if (!ResizeHelper.isResizeSupported()) {
return;
}
clearBodyContent();
final int width = 600;
final int height = 500;
final TestResizeHandler handler = new TestResizeHandler();
final HandlerRegistration handlerRegistration = Window.addResizeHandler(handler);
ResizeHelper.resizeTo(width, height);
ResizeHelper.assertSize(width, height);
ResizeHelper.resizeBy(10, 20);
ResizeHelper.assertSize(width + 10, height + 20);
delayTestFinish(1000);
Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
public boolean execute() {
if (!handler.isCalled()) {
return true; // we still didn't receive the callback, let's wait more
}
assertEquals(Window.getClientWidth(), handler.getWidth());
assertEquals(Window.getClientHeight(), handler.getHeight());
handlerRegistration.removeHandler();
finishTest();
return false;
}
}, 10);
}
/**
* Tests the ability of scroll the Window and catch scroll events.
* Failed in all modes due to HtmlUnit bug:
* https://sourceforge.net/tracker/?func=detail&aid=2897457&group_id=47038&atid=448266
* <p>
* TODO(flin): it is marked fixed, but is still not fixed.
*/
@DoNotRunWith(Platform.HtmlUnitBug)
public void testScrolling() {
// Force scroll bars to appear
Window.enableScrolling(true);
int clientHeight = Window.getClientHeight();
int clientWidth = Window.getClientWidth();
final Label largeDOM = new Label();
largeDOM.setPixelSize(clientWidth + 500, clientHeight + 500);
RootPanel.get().add(largeDOM);
// Listener for scroll events
Window.scrollTo(100, 200);
assertEquals(100, Window.getScrollLeft());
assertEquals(200, Window.getScrollTop());
Window.scrollTo(0, 0);
assertEquals(0, Window.getScrollLeft());
assertEquals(0, Window.getScrollTop());
// Cleanup the window
RootPanel.get().remove(largeDOM);
}
@SuppressWarnings("deprecation")
static class ListenerTester implements WindowResizeListener {
static int resize = 0;
public void onWindowResized(int width, int height) {
++resize;
}
public static void fire() {
resize = 0;
ResizeEvent.fire(Window.handlers, 0, 0);
}
}
@SuppressWarnings("deprecation")
public void testListenerRemoval() {
WindowResizeListener r1 = new ListenerTester();
WindowResizeListener r2 = new ListenerTester();
Window.addWindowResizeListener(r1);
Window.addWindowResizeListener(r2);
ListenerTester.fire();
assertEquals(ListenerTester.resize, 2);
Window.removeWindowResizeListener(r1);
ListenerTester.fire();
assertEquals(ListenerTester.resize, 1);
Window.removeWindowResizeListener(r2);
ListenerTester.fire();
assertEquals(ListenerTester.resize, 0);
}
}