OLD | NEW |
---|---|
(Empty) | |
1 # Copyright 2016 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 import environment | |
6 import logging | |
7 import os | |
8 import pyautogui | |
9 import time | |
10 | |
11 from PIL import Image | |
12 from selenium.webdriver.common.action_chains import ActionChains | |
13 | |
14 SCRIPT_DEBUG = 100 | |
15 | |
16 class ScreenshotGenerator: | |
17 """Base class for creation of screenshots providing utility functions.""" | |
18 | |
19 def __init__(self, name): | |
20 """Creates a new ScreenshotGenerator instance. | |
21 | |
22 Args: | |
23 name: The name of the screenshot type. | |
24 """ | |
25 self.name = name | |
26 | |
27 # The Environment, if added to any. | |
28 self.environment = None | |
29 # The webdriver from the environment. | |
30 self.driver = None | |
31 | |
32 # Mouse/Keyboard actions. | |
33 | |
34 def Click(self, selector): | |
35 """Clicks on the element described by |selector|. | |
36 | |
37 Args: | |
38 selector: The clicked element's CSS selector. | |
39 """ | |
40 | |
41 logging.log(SCRIPT_DEBUG, "action: Click %s" % selector) | |
melandory
2016/05/30 13:51:49
nit:
since it's python and you're using same patte
| |
42 element = self.WaitUntilDisplayed(selector) | |
43 element.click() | |
44 | |
45 def ClickIfClickable(self, selector): | |
46 """Clicks on the element described by |selector| if it is clickable. | |
47 | |
48 The driver's find_element_by_css_selector method defines what is clickable | |
49 -- anything for which it does not throw, is clickable. To be clickable, | |
50 the element must: | |
51 * exist in the DOM, | |
52 * be not covered by another element | |
53 * be inside the visible area. | |
54 Note that transparency does not influence clickability. | |
55 | |
56 Args: | |
57 selector: The clicked element's CSS selector. | |
58 | |
59 Returns: | |
60 True if the element is clickable (and was clicked on). | |
61 False otherwise. | |
62 """ | |
63 | |
64 logging.log(SCRIPT_DEBUG, "action: ClickIfVisible %s" % selector) | |
65 element = self.WaitUntilDisplayed(selector) | |
66 try: | |
67 element.click() | |
68 return True | |
69 except Exception: | |
70 return False | |
71 | |
72 def GoTo(self, url): | |
73 """Navigates the main frame to |url|. | |
74 | |
75 Args: | |
76 url: The URL of where to go to. | |
77 """ | |
78 | |
79 logging.log(SCRIPT_DEBUG, "action: GoTo %s" % self.name) | |
80 self.driver.get(url) | |
81 | |
82 def HoverOver(self, selector): | |
83 """Hovers over the element described by |selector|. | |
84 | |
85 Args: | |
86 selector: The CSS selector of the element to hover over. | |
87 """ | |
88 | |
89 logging.log(SCRIPT_DEBUG, "action: Hover %s" % selector) | |
90 element = self.WaitUntilDisplayed(selector) | |
91 hover = ActionChains(self.driver).move_to_element(element) | |
92 hover.perform() | |
93 | |
94 # Waiting/Displaying actions. | |
95 | |
96 def _ReturnElementIfDisplayed(self, selector): | |
97 """Returns the element described by |selector|, if displayed. | |
98 | |
99 Note: This takes neither overlapping among elements nor position with | |
100 regards to the visible area into account. | |
101 | |
102 Args: | |
103 selector: The CSS selector of the checked element. | |
104 | |
105 Returns: | |
106 The element if displayed, None otherwise. | |
107 """ | |
108 | |
109 try: | |
110 element = self.driver.find_element_by_css_selector(selector) | |
111 if element: | |
112 logging.log(SCRIPT_DEBUG, "Found element %s" % selector) | |
113 else: | |
114 logging.log(SCRIPT_DEBUG, "Did not find element %s" % selector) | |
115 return element if element.is_displayed() else None | |
116 except Exception as e: | |
117 logging.log(SCRIPT_DEBUG, "Exception %s", e) | |
118 return None | |
119 | |
120 def IsDisplayed(self, selector): | |
121 """Check if the element described by |selector| is displayed. | |
122 | |
123 Note: This takes neither overlapping among elements nor position with | |
124 regards to the visible area into account. | |
125 | |
126 Args: | |
127 selector: The CSS selector of the checked element. | |
128 | |
129 Returns: | |
130 True if the element is in the DOM and less than 100% transparent. | |
131 False otherwise. | |
132 """ | |
133 | |
134 logging.log(SCRIPT_DEBUG, "action: IsDisplayed %s" % selector) | |
135 return self._ReturnElementIfDisplayed(selector) is not None | |
136 | |
137 def Wait(self, duration): | |
138 """Wait for |duration| in seconds. | |
139 | |
140 Args: | |
141 duration: The time to wait in seconds. | |
142 | |
143 Raises: | |
144 Exception: In case the accummulated waiting limit is exceeded. | |
145 """ | |
146 | |
147 logging.log(SCRIPT_DEBUG, "action: Wait %s" % duration) | |
148 time.sleep(duration) | |
149 | |
150 def WaitUntilDisplayed(self, selector): | |
151 """Waits until the element described by |selector| is displayed. | |
152 | |
153 Args: | |
154 selector: The CSS selector of the element to wait for. | |
155 | |
156 Returns: | |
157 The displayed element. | |
158 """ | |
159 | |
160 element = self._ReturnElementIfDisplayed(selector) | |
161 while not element: | |
162 logging.log(SCRIPT_DEBUG, "action: Waiting for %s to show up" % selector) | |
163 self.Wait(1) | |
164 element = self._ReturnElementIfDisplayed(selector) | |
165 return element | |
166 | |
167 def CaptureContentScreenshot(self, selector): | |
168 """Waits until the element is displayed and captures a screenshot of it. | |
169 | |
170 The screenshot is written to self.environment.output_path. | |
171 | |
172 Args: | |
173 selector: The CSS selector of the element to take a picture of. | |
174 """ | |
175 | |
176 filename = "%s-%s.png" % (self.name, self.environment.language) | |
177 final_path = os.path.join(self.environment.output_path, filename) | |
178 tmp_path = os.path.join(self.environment.output_path, "tmp.png") | |
179 logging.log(SCRIPT_DEBUG, "Storing a screenshot to %s", final_path) | |
180 | |
181 self.HoverOver(selector) | |
182 element = self.WaitUntilDisplayed(selector) | |
183 location, size = element.location_once_scrolled_into_view, element.size | |
184 x, y = location['x'], location['y'] | |
185 w, h = size['width'], size['height'] | |
186 self.driver.save_screenshot(tmp_path) | |
187 img = Image.open(tmp_path) | |
188 img = img.crop((x, y, x + w, y + h)) | |
189 img.save(final_path, 'png') | |
190 os.remove(tmp_path) | |
191 | |
192 def CaptureWindowScreenshot(self, top=0, bottom=0, left=0, right=0): | |
193 """Takes a screenshot of the top/bottom/left/right pixels of the browser | |
194 window. | |
195 | |
196 This requires that the browser window is positioned on the top left of the | |
197 screen. | |
198 | |
199 Args: | |
200 top: Number of pixel rows to take a screenshot of. | |
201 bottom: Number of pixel rows to take a screenshot of. | |
202 left: Number of pixel columns to take a screenshot of. | |
203 right: Number of pixel columns to take a screenshot of. | |
204 """ | |
205 filename = "%s-%s.png" % (self.name, self.environment.language) | |
206 final_path = os.path.join(self.environment.output_path, filename) | |
207 tmp_path = os.path.join(self.environment.output_path, "tmp.png") | |
208 | |
209 im = pyautogui.screenshot() | |
210 im.save(tmp_path) | |
211 | |
212 img = Image.open(tmp_path) | |
213 img = img.crop((0, 0, self.driver.get_window_size()['width'], | |
214 self.driver.get_window_size()['height'])) | |
215 if top != 0: | |
216 img = img.crop((0, 0, img.size[0], top)) | |
217 if bottom != 0: | |
218 img = img.crop((0, img.size[1] - bottom, img.size[0], img.size[1])) | |
219 if left != 0: | |
220 img = img.crop((0, 0, left, img.size[1])) | |
221 if right != 0: | |
222 img = img.crop((img.size[0] - right, 0, img.size[0], img.size[1])) | |
223 img.save(final_path, 'png') | |
224 os.remove(tmp_path) | |
OLD | NEW |