| OLD | NEW |
| (Empty) |
| 1 # Copyright 2015 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 logging | |
| 6 | |
| 7 from telemetry.page import page | |
| 8 from telemetry.page import page_set | |
| 9 | |
| 10 | |
| 11 _MOVE_GOOGLE_MAPS_JS = """ | |
| 12 /** | |
| 13 * Issues/dispatches keyboard event to target element. | |
| 14 * @param {element} target Target element. | |
| 15 * @param {string} eventType One of 'keyup', 'keydown', 'keypress'. | |
| 16 * @param {number} keyCode Key code. | |
| 17 */ | |
| 18 function issueKeyEvent(target, eventType, keyCode) { | |
| 19 var event = document.createEventObject ? | |
| 20 document.createEventObject() : document.createEvent('Events'); | |
| 21 | |
| 22 if (event.initEvent) { | |
| 23 event.initEvent(eventType, true, true); | |
| 24 } | |
| 25 | |
| 26 event.keyCode = keyCode; | |
| 27 event.which = keyCode; | |
| 28 | |
| 29 target.dispatchEvent ? | |
| 30 target.dispatchEvent(event) : target.fireEvent('on' + eventType, event); | |
| 31 } | |
| 32 | |
| 33 // Map keyboard shortcut to key code mapping. | |
| 34 var MAP_KEYBOARD = { | |
| 35 LEFT: 37, | |
| 36 UP: 38, | |
| 37 RIGHT: 39, | |
| 38 DOWN: 40, | |
| 39 ZOOM_IN: 187, | |
| 40 ZOOM_OUT: 189 | |
| 41 }; | |
| 42 | |
| 43 // The scene canvas is the first one on the page apparently. The 2nd one is the | |
| 44 // minimap. I'd rely on the canvas ordering instead of the class since Tactile's | |
| 45 // obfuscating classes soon. | |
| 46 var sceneCanvas = document.querySelector('canvas'); | |
| 47 | |
| 48 /** | |
| 49 * Moves Google maps. | |
| 50 * @param {string} action Action defined in MAP_KEYBOARD. | |
| 51 * @param {number} duration_msecs Duration (in ms) of the action. | |
| 52 */ | |
| 53 function moveMap(action, duration_msecs) { | |
| 54 keycode = MAP_KEYBOARD[action]; | |
| 55 issueKeyEvent(sceneCanvas, 'keydown', keycode); | |
| 56 setTimeout(function() {issueKeyEvent(sceneCanvas, 'keyup', keycode);}, | |
| 57 duration_msecs); | |
| 58 } | |
| 59 | |
| 60 /** | |
| 61 * Creates and dispatches mouse event. | |
| 62 * @param {object} target DOM element to dispatch event to. | |
| 63 * @param {string} eventType Mouse event, one of 'mousedown', 'mouseup', | |
| 64 * 'mousemove' event. | |
| 65 * @param {number} x clientX position. | |
| 66 * @param {number} y clientY position. | |
| 67 * @param {number} delay Milliseconds delay to dispatch the event. | |
| 68 */ | |
| 69 function dispatchMouseEvent(target, eventType, x, y, delay) { | |
| 70 setTimeout(function() { | |
| 71 /* TODO(deanliao): investigate why the new MouseEvent creator won't work. | |
| 72 var button = eventType == 'mouseup' ? -1 : 0; | |
| 73 var event = new MouseEvent( | |
| 74 eventType, | |
| 75 {clientX: x, | |
| 76 clientY: y, | |
| 77 button: button}); | |
| 78 */ | |
| 79 | |
| 80 var event = document.createEvent('MouseEvents'); | |
| 81 var detail = eventType == 'mousemove' ? 0 : 1; | |
| 82 event.initMouseEvent(eventType, true, true, window, | |
| 83 detail, x, y, x, y); | |
| 84 | |
| 85 target.dispatchEvent(event); | |
| 86 | |
| 87 }, delay); | |
| 88 } | |
| 89 | |
| 90 | |
| 91 /** | |
| 92 * Drag-n-drops mouse linearly for a while. | |
| 93 * @param {object} target DOM element to dispatch event to. | |
| 94 * @param {number} startX Starting clientX position. | |
| 95 * @param {number} startY Starting clientY position. | |
| 96 * @param {number} endX Starting clientX position. | |
| 97 * @param {number} endY Starting clientY position. | |
| 98 * @param {number} duration Drag for milliseconds. | |
| 99 */ | |
| 100 function linearMouseDragDrop(target, startX, startY, endX, endY, duration) { | |
| 101 var interval = 10; | |
| 102 var numSteps = Math.floor(duration / interval) - 1; | |
| 103 var deltaX = (endX - startX) / numSteps; | |
| 104 var deltaY = (endY - startY) / numSteps; | |
| 105 var x = startX; | |
| 106 var y = startY; | |
| 107 var delay = 0; | |
| 108 dispatchMouseEvent(target, 'mousedown', x, y, delay); | |
| 109 for (i = 1; i < numSteps; i++) { | |
| 110 x = Math.floor(startX + i * deltaX); | |
| 111 y = Math.floor(startY + i * deltaY); | |
| 112 delay += interval; | |
| 113 dispatchMouseEvent(target, 'mousemove', x, y, delay); | |
| 114 } | |
| 115 dispatchMouseEvent(target, 'mouseup', endX, endY, delay + interval); | |
| 116 } | |
| 117 """ | |
| 118 | |
| 119 | |
| 120 class MapsEarthPage(page.Page): | |
| 121 """Page for surfing Google Maps with Earth layer.""" | |
| 122 | |
| 123 _MAP_MODE_SWITCHER = '.widget-minimap-shim-button' | |
| 124 _START_END_COORD = { | |
| 125 'LEFT': (700, 380, 20, 380), | |
| 126 'RIGHT': (20, 380, 700, 380), | |
| 127 'UP': (500, 600, 500, 20), | |
| 128 'DOWN': (500, 20, 500, 600)} | |
| 129 | |
| 130 def __init__(self, parent_page_set, url, page_name, map_load_wait_secs=10, | |
| 131 drag_duration_ms=500): | |
| 132 super(MapsEarthPage, self).__init__( | |
| 133 url=url, | |
| 134 page_set=parent_page_set, | |
| 135 name=page_name) | |
| 136 self._map_load_wait_sec = map_load_wait_secs | |
| 137 self._drag_duration_ms = drag_duration_ms | |
| 138 | |
| 139 def CanRunOnBrowser(self, browser_info): | |
| 140 if not browser_info.HasWebGLSupport(): | |
| 141 logging.warning('Browser does not support webgl, skipping test') | |
| 142 return False | |
| 143 return True | |
| 144 | |
| 145 def RunNavigateSteps(self, action_runner): | |
| 146 super(MapsEarthPage, self).RunNavigateSteps(action_runner) | |
| 147 logging.info('Wait for Google Maps mode switcher') | |
| 148 action_runner.WaitForElement(selector=self._MAP_MODE_SWITCHER) | |
| 149 logging.info('Loaded. Wait for %d more seconds...' % | |
| 150 self._map_load_wait_sec) | |
| 151 action_runner.Wait(self._map_load_wait_sec) | |
| 152 self.PrepareInteraction(action_runner) | |
| 153 | |
| 154 def MouseDrag(self, action_runner, direction, duration_ms): | |
| 155 """Drags mouse on the map. | |
| 156 | |
| 157 Args: | |
| 158 action_runner: Telemetry action runner. | |
| 159 direction: Drag direction. One of 'UP', 'DOWN', 'LEFT', 'RIGHT'. | |
| 160 duration_ms: Duration of the drag. | |
| 161 """ | |
| 162 if direction not in self._START_END_COORD: | |
| 163 logging.error('Invalid direction %r. Should be one of %r', direction, | |
| 164 self._START_END_COORD.keys()) | |
| 165 return | |
| 166 start_end_coord = ', '.join( | |
| 167 str(x) for x in self._START_END_COORD[direction]) | |
| 168 js = 'linearMouseDragDrop(sceneCanvas, %s, %d);' % (start_end_coord, | |
| 169 duration_ms) | |
| 170 logging.info('MouseDrag %s for %d ms. Execute %s', direction, duration_ms, | |
| 171 js) | |
| 172 action_runner.ExecuteJavaScript(js) | |
| 173 action_runner.Wait(duration_ms / 1000.0 + 0.2) | |
| 174 | |
| 175 def RunPageInteractions(self, action_runner): | |
| 176 logging.info('RunPageInteractions') | |
| 177 for action in ['DOWN', 'LEFT', 'LEFT', 'UP', 'RIGHT', 'RIGHT', 'UP', | |
| 178 'LEFT', 'LEFT', 'UP', 'RIGHT', 'RIGHT', 'UP', 'LEFT', | |
| 179 'LEFT']: | |
| 180 self.MouseDrag(action_runner, action, self._drag_duration_ms) | |
| 181 | |
| 182 # TODO(deanliao): figure out why keyboard event doesn't work. | |
| 183 # for action in | |
| 184 # logging.info('moveMap ' + action) | |
| 185 # action_runner.ExecuteJavaScript( | |
| 186 # "moveMap('%s', %d);" % (action, self._KEYDOWN_MSEC)) | |
| 187 # action_runner.Wait(self._ACTION_INTERVAL_SECS) | |
| 188 | |
| 189 def PrepareInteraction(self, action_runner): | |
| 190 action_runner.ExecuteJavaScript(_MOVE_GOOGLE_MAPS_JS) | |
| 191 logging.info('_MOVE_GOOGLE_MAPS_JS injected.') | |
| 192 | |
| 193 | |
| 194 class MapsEarthPageSet(page_set.PageSet): | |
| 195 """Page set for Google Maps with Earth layer.""" | |
| 196 | |
| 197 def __init__(self): | |
| 198 super(MapsEarthPageSet, self).__init__( | |
| 199 archive_data_file='data/maps_earth.json', | |
| 200 bucket=page_set.PUBLIC_BUCKET) | |
| 201 | |
| 202 self.AddUserStory( | |
| 203 MapsEarthPage( | |
| 204 self, | |
| 205 'https://www.google.com/maps/@37.7502889,-122.4791582,15z', | |
| 206 'Maps.SanFrancisco', | |
| 207 map_load_wait_secs=3, | |
| 208 drag_duration_ms=1500)) | |
| 209 | |
| 210 # Temporary disable Earth test as it doesn't run smooth yet. | |
| 211 # self.AddUserStory( | |
| 212 # MapsEarthPage( | |
| 213 # self, | |
| 214 # 'https://goo.gl/maps/NRtaW', | |
| 215 # 'Maps.SanFranciscoEarth', | |
| 216 # map_load_wait_secs=10, | |
| 217 # drag_duration_ms=2000)) | |
| OLD | NEW |