1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.content.browser.test.util;
7 import android.graphics.Rect;
8 import android.test.ActivityInstrumentationTestCase2;
9 import android.util.JsonReader;
11 import java.io.IOException;
12 import java.io.StringReader;
13 import java.util.concurrent.TimeoutException;
15 import junit.framework.Assert;
17 import org.chromium.content.browser.ContentView;
20 * Collection of DOM-based utilities.
22 public class DOMUtils {
25 * Returns the rect boundaries for a node by its id.
27 public static Rect getNodeBounds(
28 final ContentView view, TestCallbackHelperContainer viewClient, String nodeId)
29 throws InterruptedException, TimeoutException {
30 StringBuilder sb = new StringBuilder();
31 sb.append("(function() {");
32 sb.append(" var node = document.getElementById('" + nodeId + "');");
33 sb.append(" if (!node) return null;");
34 sb.append(" var width = node.offsetWidth;");
35 sb.append(" var height = node.offsetHeight;");
36 sb.append(" var x = -window.scrollX;");
37 sb.append(" var y = -window.scrollY;");
39 sb.append(" x += node.offsetLeft;");
40 sb.append(" y += node.offsetTop;");
41 sb.append(" } while (node = node.offsetParent);");
42 sb.append(" return [ x, y, width, height ];");
45 String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
46 view, viewClient, sb.toString());
48 Assert.assertFalse("Failed to retrieve bounds for " + nodeId,
49 jsonText.trim().equalsIgnoreCase("null"));
51 JsonReader jsonReader = new JsonReader(new StringReader(jsonText));
52 int[] bounds = new int[4];
54 jsonReader.beginArray();
56 while (jsonReader.hasNext()) {
57 bounds[i++] = jsonReader.nextInt();
59 jsonReader.endArray();
60 Assert.assertEquals("Invalid bounds returned.", 4, i);
63 } catch (IOException exception) {
64 Assert.fail("Failed to evaluate JavaScript: " + jsonText + "\n" + exception);
67 return new Rect(bounds[0], bounds[1], bounds[0] + bounds[2], bounds[1] + bounds[3]);
71 * Focus a DOM node by its id.
73 public static void focusNode(ActivityInstrumentationTestCase2 activityTestCase,
74 final ContentView view, TestCallbackHelperContainer viewClient, String nodeId)
75 throws InterruptedException, TimeoutException {
76 StringBuilder sb = new StringBuilder();
77 sb.append("(function() {");
78 sb.append(" var node = document.getElementById('" + nodeId + "');");
79 sb.append(" if (node) node.focus();");
82 JavaScriptUtils.executeJavaScriptAndWaitForResult(view, viewClient, sb.toString());
86 * Click a DOM node by its id.
88 public static void clickNode(ActivityInstrumentationTestCase2 activityTestCase,
89 final ContentView view, TestCallbackHelperContainer viewClient, String nodeId)
90 throws InterruptedException, TimeoutException {
91 int[] clickTarget = getClickTargetForNode(view, viewClient, nodeId);
92 TouchCommon touchCommon = new TouchCommon(activityTestCase);
93 touchCommon.singleClickView(view, clickTarget[0], clickTarget[1]);
97 * Long-press a DOM node by its id.
99 public static void longPressNode(ActivityInstrumentationTestCase2 activityTestCase,
100 final ContentView view, TestCallbackHelperContainer viewClient, String nodeId)
101 throws InterruptedException, TimeoutException {
102 int[] clickTarget = getClickTargetForNode(view, viewClient, nodeId);
103 TouchCommon touchCommon = new TouchCommon(activityTestCase);
104 touchCommon.longPressView(view, clickTarget[0], clickTarget[1]);
108 * Scrolls the view to ensure that the required DOM node is visible.
110 public static void scrollNodeIntoView(final ContentView view,
111 TestCallbackHelperContainer viewClient, String nodeId)
112 throws InterruptedException, TimeoutException {
113 JavaScriptUtils.executeJavaScriptAndWaitForResult(view, viewClient,
114 "document.getElementById('" + nodeId + "').scrollIntoView()");
118 * Returns the contents of the node by its id.
120 public static String getNodeContents(final ContentView view,
121 TestCallbackHelperContainer viewClient, String nodeId)
122 throws InterruptedException, TimeoutException {
123 return getNodeField("textContent", view, viewClient, nodeId);
127 * Returns the value of the node by its id.
129 public static String getNodeValue(final ContentView view,
130 TestCallbackHelperContainer viewClient, String nodeId)
131 throws InterruptedException, TimeoutException {
132 return getNodeField("value", view, viewClient, nodeId);
135 private static String getNodeField(String fieldName, final ContentView view,
136 TestCallbackHelperContainer viewClient, String nodeId)
137 throws InterruptedException, TimeoutException {
138 StringBuilder sb = new StringBuilder();
139 sb.append("(function() {");
140 sb.append(" var node = document.getElementById('" + nodeId + "');");
141 sb.append(" if (!node) return null;");
142 sb.append(" if (!node." + fieldName +") return null;");
143 sb.append(" return [ node." + fieldName + " ];");
146 String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
147 view, viewClient, sb.toString());
148 Assert.assertFalse("Failed to retrieve contents for " + nodeId,
149 jsonText.trim().equalsIgnoreCase("null"));
151 JsonReader jsonReader = new JsonReader(new StringReader(jsonText));
154 jsonReader.beginArray();
155 if (jsonReader.hasNext()) value = jsonReader.nextString();
156 jsonReader.endArray();
157 Assert.assertNotNull("Invalid contents returned.", value);
160 } catch (IOException exception) {
161 Assert.fail("Failed to evaluate JavaScript: " + jsonText + "\n" + exception);
167 * Returns click targets for a given DOM node.
169 private static int[] getClickTargetForNode(final ContentView view,
170 TestCallbackHelperContainer viewClient, String nodeName)
171 throws InterruptedException, TimeoutException {
172 Rect bounds = getNodeBounds(view, viewClient, nodeName);
173 Assert.assertNotNull("Failed to get DOM element bounds of '" + nodeName + "'.", bounds);
175 int clickX = (int) view.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterX())
176 + (int) view.getContentViewCore().getViewportSizeOffsetWidthPix();
177 int clickY = (int) view.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterY())
178 + (int) view.getContentViewCore().getViewportSizeOffsetHeightPix();
179 return new int[] { clickX, clickY };