diff options
author | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-17 00:19:32 +0000 |
---|---|---|
committer | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-17 00:19:32 +0000 |
commit | c158a6699a9f5e5f56d913c0b06e0d83e8358591 (patch) | |
tree | 727e3eb0a5aac10658e35d2e389b057faed103bf /chrome/renderer/resources | |
parent | c7eca5b2c6f9a527d18d00486d2d7cd7dca9c7b1 (diff) | |
download | chromium_src-c158a6699a9f5e5f56d913c0b06e0d83e8358591.zip chromium_src-c158a6699a9f5e5f56d913c0b06e0d83e8358591.tar.gz chromium_src-c158a6699a9f5e5f56d913c0b06e0d83e8358591.tar.bz2 |
Add support for DOM interaction in browser tests via C++.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/660046
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41789 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/resources')
-rw-r--r-- | chrome/renderer/resources/dom_automation.js | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/chrome/renderer/resources/dom_automation.js b/chrome/renderer/resources/dom_automation.js new file mode 100644 index 0000000..16a4dd0 --- /dev/null +++ b/chrome/renderer/resources/dom_automation.js @@ -0,0 +1,234 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// dom_automation.js +// Methods for performing common DOM operations. Used in Chrome testing +// involving the DomAutomationController. + +var domAutomation = domAutomation || {}; + +(function() { + // |objects| is used to track objects which are sent back to the + // DomAutomationController. Since JavaScript does not have a map type, + // |objects| is simply an object in which the property name and + // property value serve as the key-value pair. The key is the handle number + // and the value is the tracked object. + domAutomation.objects = {}; + domAutomation.nextHandle = 1; + + // Returns |value| after converting it to an acceptable type for return, if + // necessary. + function getConvertedValue(value) { + if (typeof value == "undefined" || !value) { + return ""; + } + if (value instanceof Array) { + var result = []; + for (var i = 0; i < value.length; i++) { + result.push(getConvertedValue(value[i])); + } + return result; + } + if (typeof(value) == "object") { + var handle = getHandleForObject(value); + if (handle == -1) { + // Track this object. + var handle = domAutomation.nextHandle++; + domAutomation.objects[handle] = value; + } + return handle; + } + return value; + } + + // Returns the handle for |obj|, or -1 if no handle exists. + function getHandleForObject(obj) { + for (var property in domAutomation.objects) { + if (domAutomation.objects[property] == obj) + return parseInt(property); + } + return -1; + } + + // Safely evaluates |javascript| and sends a response back via the + // DomAutomationController. See javascript_execution_controller.cc + // for more details. + domAutomation.evaluateJavaScript = function(javascript) { + try { + var result = [true, "", getConvertedValue(eval(javascript))]; + } + catch (exception) { + var message = exception.message; + if (typeof message != "string") + message = JSON.stringify(message); + var result = [false, message, exception]; + } + domAutomationController.sendJSON(JSON.stringify(result)); + } + + // Stops tracking the object associated with |handle|. + domAutomation.removeObject = function(handle) { + delete domAutomation.objects[handle]; + } + + // Stops tracking all objects. + domAutomation.removeAll = function() { + domAutomation.objects = {}; + domAutomation.nextHandle = 1; + } + + // Gets the object associated with this |handle|. + domAutomation.getObject = function(handle) { + return domAutomation.objects[handle]; + } + + // Converts an indexable list with a length property to an array. + function getArray(list) { + var arr = []; + for (var i = 0; i < list.length; i++) { + arr.push(list[i]); + } + return arr; + } + + // Removes whitespace at the beginning and end of |text|. + function trim(text) { + return text.replace(/^\s+|\s+$/g, ""); + } + + // Returns the window (which is a sub window of |win|) which + // directly contains |doc|. May return null. + function findWindowForDocument(win, doc) { + if (win.document == doc) + return win; + for (var i = 0; i < win.frames.length; i++) { + if (findWindowForDocument(win.frames[i], doc)) + return win.frames[i]; + } + return null; + } + + //// DOM Element automation methods + //// See dom_element_proxy.h for method details. + + domAutomation.getDocumentFromFrame = function(element, frameNames) { + // Find the window this element is in. + var containingDocument = element.ownerDocument || element; + var frame = findWindowForDocument(window, containingDocument); + + for (var i = 0; i < frameNames.length; i++) { + frame = frame.frames[frameNames[i]]; + if (typeof frame == "undefined" || !frame) { + return null; + } + } + return frame.document; + } + + domAutomation.findByXPath = function(context, xpath) { + var xpathResult = + document.evaluate(xpath, context, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + var elements = []; + for (var i = 0; i < xpathResult.snapshotLength; i++) { + elements.push(xpathResult.snapshotItem(i)); + } + return elements; + } + + domAutomation.find1ByXPath = function(context, xpath) { + var xpathResult = + document.evaluate(xpath, context, null, + XPathResult.FIRST_ORDERED_NODE_TYPE, null); + return xpathResult.singleNodeValue; + } + + domAutomation.findBySelectors = function(context, selectors) { + return getArray(context.querySelectorAll(selectors)); + } + + domAutomation.find1BySelectors = function(context, selectors) { + return context.querySelector(selectors); + } + + domAutomation.findByText = function(context, text) { + // Find all elements containing this text and all inputs containing + // this text. + var xpath = ".//*[contains(text(), '" + text + "')] | " + + ".//input[contains(@value, '" + text + "')]"; + var elements = domAutomation.findByXPath(context, xpath); + + // Limit to what is visible. + var final_list = []; + for (var i = 0; i < elements.length; i++) { + if (domAutomation.isVisible(elements[i])) + final_list.push(elements[i]); + } + return final_list; + } + + domAutomation.find1ByText = function(context, text) { + return domAutomation.findByText(context, text)[0]; + } + + domAutomation.click = function(element) { + var evt = document.createEvent('MouseEvents'); + evt.initMouseEvent('click', true, true, window, + 0, 0, 0, 0, 0, false, false, + false, false, 0, null); + while (element) { + element.dispatchEvent(evt); + element = element.parentNode; + } + } + + domAutomation.type = function(element, text) { + if (element instanceof HTMLTextAreaElement || + (element instanceof HTMLInputElement && element.type == "text")) { + element.value += text; + return true; + } + return false; + } + + domAutomation.setText = function(element, text) { + if (element instanceof HTMLTextAreaElement || + (element instanceof HTMLInputElement && element.type == "text")) { + element.value = text; + return true; + } + return false; + } + + domAutomation.getText = function(element) { + if (element instanceof Text) { + return trim(element.textContent); + } + else if (element instanceof HTMLTextAreaElement || + (element instanceof HTMLInputElement)) { + return element.value || ""; + } + var childrenText = ""; + for (var i = 0; i < element.childNodes.length; i++) { + childrenText += domAutomation.getText(element.childNodes[i]); + } + return childrenText; + } + + domAutomation.getInnerHTML = function(element) { + return trim(element.innerHTML); + } + + domAutomation.isVisible = function(element) { + while (element.style) { + if (element.style.display == 'none' || + element.style.visibility == 'hidden' || + element.style.visibility == 'collapse') { + return false; + } + element = element.parentNode; + } + return true; + } +})(); |