OLD | NEW |
---|---|
1 # Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import re | |
6 | |
5 class PageActionNotSupported(Exception): | 7 class PageActionNotSupported(Exception): |
6 pass | 8 pass |
7 | 9 |
8 class PageActionFailed(Exception): | 10 class PageActionFailed(Exception): |
9 pass | 11 pass |
10 | 12 |
11 | 13 |
12 class PageAction(object): | 14 class PageAction(object): |
13 """Represents an action that a user might try to perform to a page.""" | 15 """Represents an action that a user might try to perform to a page.""" |
14 | 16 |
15 def __init__(self, attributes=None): | 17 def __init__(self, attributes=None): |
16 if attributes: | 18 if attributes: |
17 for k, v in attributes.iteritems(): | 19 for k, v in attributes.iteritems(): |
18 setattr(self, k, v) | 20 setattr(self, k, v) |
19 | 21 |
20 def WillRunAction(self, tab): | 22 def WillRunAction(self, tab): |
21 """Override to do action-specific setup before | 23 """Override to do action-specific setup before |
22 Test.WillRunAction is called.""" | 24 Test.WillRunAction is called.""" |
23 pass | 25 pass |
24 | 26 |
25 def RunAction(self, tab): | 27 def RunAction(self, tab): |
26 raise NotImplementedError() | 28 raise NotImplementedError() |
27 | 29 |
28 def CleanUp(self, tab): | 30 def CleanUp(self, tab): |
29 pass | 31 pass |
32 | |
33 | |
34 def EvaluateCallbackWithElement( | |
35 tab, callback_js, selector=None, text=None, element_function=None, | |
36 wait=False, timeout=60): | |
37 """Evaluates the JavaScript callback with the given element. | |
38 | |
39 The element may be selected via selector, text, or element_function. | |
40 Only one of these arguments must be specified. | |
41 | |
42 Returns: | |
43 The callback's return value, if any. The return value must be | |
44 convertible to JSON. | |
45 | |
46 Args: | |
47 tab: A telemetry.core.Tab object. | |
48 callback_js: The JavaScript callback to call (as string). | |
49 The callback receive 2 parameters: the element, and information | |
50 string about what method was used to retrieve the element. | |
51 Example: ''' | |
52 function(element, info) { | |
53 if (!element) { | |
54 throw Error('Can not find element: ' + info); | |
55 } | |
56 element.click() | |
57 }''' | |
58 selector: A CSS selector describing the element. | |
59 text: The element must contains this exact text. | |
60 element_function: A JavaScript function (as string) that is used | |
61 to retrieve the element. For example: | |
62 '(function() { return foo.element; })()'. | |
nednguyen
2014/06/14 17:12:13
The naming element_function is misleading, I think
chrishenry
2014/06/14 17:30:51
I think you're right. It's not super confusing, bu
| |
63 wait: Whether to wait for the return value to be true. | |
64 timeout: The timeout for wait (if waiting). | |
65 """ | |
66 count = 0 | |
67 info_msg = '' | |
68 if element_function is not None: | |
69 count = count + 1 | |
70 info_msg = 'using element_function "%s"' % re.escape(element_function) | |
71 if selector is not None: | |
72 count = count + 1 | |
73 info_msg = 'using selector "%s"' % _EscapeSelector(selector) | |
74 element_function = 'document.querySelector("%s")' % _EscapeSelector( | |
75 selector) | |
76 if text is not None: | |
77 count = count + 1 | |
78 info_msg = 'using exact text match "%s"' % re.escape(text) | |
79 element_function = ''' | |
80 (function() { | |
81 function _findElement(element, text) { | |
82 if (element.innerHTML == text) { | |
83 return element; | |
84 } | |
85 | |
86 var childNodes = element.childNodes; | |
87 for (var i = 0, len = childNodes.length; i < len; ++i) { | |
88 var found = _findElement(childNodes[i], text); | |
89 if (found) { | |
90 return found; | |
91 } | |
92 } | |
93 return null; | |
94 } | |
95 return _findElement(document, '%s'); | |
96 })()''' % text | |
97 | |
98 if count != 1: | |
99 raise PageActionFailed( | |
100 'Must specify 1 way to retrieve element, but %s was specified.' % count) | |
101 | |
102 code = ''' | |
103 (function() { | |
104 var element = %s; | |
105 var callback = %s; | |
106 return callback(element, '%s'); | |
107 })()''' % (element_function, callback_js, info_msg) | |
108 | |
109 if wait: | |
110 tab.WaitForJavaScriptExpression(code, timeout) | |
111 return True | |
112 else: | |
113 return tab.EvaluateJavaScript(code) | |
114 | |
115 def _EscapeSelector(selector): | |
116 return selector.replace('\'', '\\\'') | |
OLD | NEW |