Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / public / test / android / javatests / src / org / chromium / content / browser / test / util / DOMUtils.java
1 // Copyright 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.
4
5 package org.chromium.content.browser.test.util;
6
7 import android.graphics.Rect;
8 import android.test.ActivityInstrumentationTestCase2;
9 import android.util.JsonReader;
10
11 import junit.framework.Assert;
12
13 import org.chromium.content.browser.ContentViewCore;
14
15 import java.io.IOException;
16 import java.io.StringReader;
17 import java.util.concurrent.TimeoutException;
18
19 /**
20  * Collection of DOM-based utilities.
21  */
22 public class DOMUtils {
23
24     /**
25      * Returns the rect boundaries for a node by its id.
26      */
27     public static Rect getNodeBounds(final ContentViewCore viewCore, String nodeId)
28             throws InterruptedException, TimeoutException {
29         StringBuilder sb = new StringBuilder();
30         sb.append("(function() {");
31         sb.append("  var node = document.getElementById('" + nodeId + "');");
32         sb.append("  if (!node) return null;");
33         sb.append("  var width = Math.round(node.offsetWidth);");
34         sb.append("  var height = Math.round(node.offsetHeight);");
35         sb.append("  var x = -window.scrollX;");
36         sb.append("  var y = -window.scrollY;");
37         sb.append("  do {");
38         sb.append("    x += node.offsetLeft;");
39         sb.append("    y += node.offsetTop;");
40         sb.append("  } while (node = node.offsetParent);");
41         sb.append("  return [ Math.round(x), Math.round(y), width, height ];");
42         sb.append("})();");
43
44         String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
45                 viewCore, sb.toString());
46
47         Assert.assertFalse("Failed to retrieve bounds for " + nodeId,
48                 jsonText.trim().equalsIgnoreCase("null"));
49
50         JsonReader jsonReader = new JsonReader(new StringReader(jsonText));
51         int[] bounds = new int[4];
52         try {
53             jsonReader.beginArray();
54             int i = 0;
55             while (jsonReader.hasNext()) {
56                 bounds[i++] = jsonReader.nextInt();
57             }
58             jsonReader.endArray();
59             Assert.assertEquals("Invalid bounds returned.", 4, i);
60
61             jsonReader.close();
62         } catch (IOException exception) {
63             Assert.fail("Failed to evaluate JavaScript: " + jsonText + "\n" + exception);
64         }
65
66         return new Rect(bounds[0], bounds[1], bounds[0] + bounds[2], bounds[1] + bounds[3]);
67     }
68
69     /**
70      * Focus a DOM node by its id.
71      */
72     public static void focusNode(final ContentViewCore viewCore, String nodeId)
73             throws InterruptedException, TimeoutException {
74         StringBuilder sb = new StringBuilder();
75         sb.append("(function() {");
76         sb.append("  var node = document.getElementById('" + nodeId + "');");
77         sb.append("  if (node) node.focus();");
78         sb.append("})();");
79
80         JavaScriptUtils.executeJavaScriptAndWaitForResult(viewCore, sb.toString());
81     }
82
83     /**
84      * Click a DOM node by its id.
85      */
86     public static void clickNode(ActivityInstrumentationTestCase2 activityTestCase,
87             final ContentViewCore viewCore, String nodeId)
88             throws InterruptedException, TimeoutException {
89         int[] clickTarget = getClickTargetForNode(viewCore, nodeId);
90         TouchCommon touchCommon = new TouchCommon(activityTestCase);
91         touchCommon.singleClickView(viewCore.getContainerView(), clickTarget[0], clickTarget[1]);
92     }
93
94     /**
95      * Long-press a DOM node by its id.
96      */
97     public static void longPressNode(ActivityInstrumentationTestCase2 activityTestCase,
98             final ContentViewCore viewCore, String nodeId)
99             throws InterruptedException, TimeoutException {
100         int[] clickTarget = getClickTargetForNode(viewCore, nodeId);
101         TouchCommon touchCommon = new TouchCommon(activityTestCase);
102         touchCommon.longPressView(viewCore.getContainerView(), clickTarget[0], clickTarget[1]);
103     }
104
105     /**
106      * Scrolls the view to ensure that the required DOM node is visible.
107      */
108     public static void scrollNodeIntoView(ContentViewCore viewCore, String nodeId)
109             throws InterruptedException, TimeoutException {
110         JavaScriptUtils.executeJavaScriptAndWaitForResult(viewCore,
111                 "document.getElementById('" + nodeId + "').scrollIntoView()");
112     }
113
114     /**
115      * Returns the contents of the node by its id.
116      */
117     public static String getNodeContents(ContentViewCore viewCore, String nodeId)
118             throws InterruptedException, TimeoutException {
119         return getNodeField("textContent", viewCore, nodeId);
120     }
121
122     /**
123      * Returns the value of the node by its id.
124      */
125     public static String getNodeValue(final ContentViewCore viewCore, String nodeId)
126             throws InterruptedException, TimeoutException {
127         return getNodeField("value", viewCore, nodeId);
128     }
129
130     private static String getNodeField(String fieldName, final ContentViewCore viewCore,
131             String nodeId)
132             throws InterruptedException, TimeoutException {
133         StringBuilder sb = new StringBuilder();
134         sb.append("(function() {");
135         sb.append("  var node = document.getElementById('" + nodeId + "');");
136         sb.append("  if (!node) return null;");
137         sb.append("  if (!node." + fieldName + ") return null;");
138         sb.append("  return [ node." + fieldName + " ];");
139         sb.append("})();");
140
141         String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
142                 viewCore, sb.toString());
143         Assert.assertFalse("Failed to retrieve contents for " + nodeId,
144                 jsonText.trim().equalsIgnoreCase("null"));
145
146         JsonReader jsonReader = new JsonReader(new StringReader(jsonText));
147         String value = null;
148         try {
149             jsonReader.beginArray();
150             if (jsonReader.hasNext()) value = jsonReader.nextString();
151             jsonReader.endArray();
152             Assert.assertNotNull("Invalid contents returned.", value);
153
154             jsonReader.close();
155         } catch (IOException exception) {
156             Assert.fail("Failed to evaluate JavaScript: " + jsonText + "\n" + exception);
157         }
158         return value;
159     }
160
161     /**
162      * Wait until a given node has non-zero bounds.
163      * @return Whether the node started having non-zero bounds.
164      */
165     public static boolean waitForNonZeroNodeBounds(final ContentViewCore viewCore,
166             final String nodeName)
167             throws InterruptedException {
168         return CriteriaHelper.pollForCriteria(new Criteria() {
169             @Override
170             public boolean isSatisfied() {
171                 try {
172                     return !DOMUtils.getNodeBounds(viewCore, nodeName).isEmpty();
173                 } catch (InterruptedException e) {
174                     // Intentionally do nothing
175                     return false;
176                 } catch (TimeoutException e) {
177                     // Intentionally do nothing
178                     return false;
179                 }
180             }
181         });
182     }
183
184     /**
185      * Returns click targets for a given DOM node.
186      */
187     private static int[] getClickTargetForNode(ContentViewCore viewCore, String nodeName)
188             throws InterruptedException, TimeoutException {
189         Rect bounds = getNodeBounds(viewCore, nodeName);
190         Assert.assertNotNull("Failed to get DOM element bounds of '" + nodeName + "'.", bounds);
191
192         int clickX = (int) viewCore.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterX())
193                 + viewCore.getViewportSizeOffsetWidthPix();
194         int clickY = (int) viewCore.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterY())
195                 + viewCore.getViewportSizeOffsetHeightPix();
196         return new int[] { clickX, clickY };
197     }
198 }