1import imghdr 2import struct 3from base64 import decodebytes 4 5from webdriver import Element, NoSuchAlertException, WebDriverException 6 7 8# WebDriver specification ID: dfn-error-response-data 9errors = { 10 "element click intercepted": 400, 11 "element not selectable": 400, 12 "element not interactable": 400, 13 "insecure certificate": 400, 14 "invalid argument": 400, 15 "invalid cookie domain": 400, 16 "invalid coordinates": 400, 17 "invalid element state": 400, 18 "invalid selector": 400, 19 "invalid session id": 404, 20 "javascript error": 500, 21 "move target out of bounds": 500, 22 "no such alert": 404, 23 "no such cookie": 404, 24 "no such element": 404, 25 "no such frame": 404, 26 "no such window": 404, 27 "script timeout": 500, 28 "session not created": 500, 29 "stale element reference": 404, 30 "timeout": 500, 31 "unable to set cookie": 500, 32 "unable to capture screen": 500, 33 "unexpected alert open": 500, 34 "unknown command": 404, 35 "unknown error": 500, 36 "unknown method": 405, 37 "unsupported operation": 500, 38} 39 40 41def assert_error(response, error_code): 42 """ 43 Verify that the provided webdriver.Response instance described 44 a valid error response as defined by `dfn-send-an-error` and 45 the provided error code. 46 47 :param response: ``webdriver.Response`` instance. 48 :param error_code: String value of the expected error code 49 """ 50 assert response.status == errors[error_code] 51 assert "value" in response.body 52 assert response.body["value"]["error"] == error_code 53 assert isinstance(response.body["value"]["message"], str) 54 assert isinstance(response.body["value"]["stacktrace"], str) 55 assert_response_headers(response.headers) 56 57 58def assert_success(response, value=None): 59 """ 60 Verify that the provided webdriver.Response instance described 61 a valid success response as defined by `dfn-send-a-response` and 62 the provided response value. 63 64 :param response: ``webdriver.Response`` instance. 65 :param value: Expected value of the response body, if any. 66 """ 67 assert response.status == 200, str(response.error) 68 69 if value is not None: 70 assert response.body["value"] == value 71 72 assert_response_headers(response.headers) 73 return response.body.get("value") 74 75 76def assert_response_headers(headers): 77 """ 78 Method to assert response headers for WebDriver requests 79 80 :param headers: dict with header data 81 """ 82 assert 'cache-control' in headers 83 assert 'no-cache' == headers['cache-control'] 84 assert 'content-type' in headers 85 assert 'application/json; charset=utf-8' == headers['content-type'] 86 87 88def assert_dialog_handled(session, expected_text, expected_retval): 89 # If there were any existing dialogs prior to the creation of this 90 # fixture's dialog, then the "Get Alert Text" command will return 91 # successfully. In that case, the text must be different than that 92 # of this fixture's dialog. 93 try: 94 assert session.alert.text != expected_text, ( 95 "User prompt with text '{}' was not handled.".format(expected_text)) 96 97 except NoSuchAlertException: 98 # If dialog has been closed and no other one is open, check its return value 99 prompt_retval = session.execute_script(" return window.dialog_return_value;") 100 assert prompt_retval == expected_retval 101 102 103def assert_files_uploaded(session, element, files): 104 105 def get_file_contents(file_index): 106 return session.execute_async_script(""" 107 let files = arguments[0].files; 108 let index = arguments[1]; 109 let resolve = arguments[2]; 110 111 var reader = new FileReader(); 112 reader.onload = function(event) { 113 resolve(reader.result); 114 }; 115 reader.readAsText(files[index]); 116 """, (element, file_index)) 117 118 def get_uploaded_file_names(): 119 return session.execute_script(""" 120 let fileList = arguments[0].files; 121 let files = []; 122 123 for (var i = 0; i < fileList.length; i++) { 124 files.push(fileList[i].name); 125 } 126 127 return files; 128 """, args=(element,)) 129 130 expected_file_names = [str(f.basename) for f in files] 131 assert get_uploaded_file_names() == expected_file_names 132 133 for index, f in enumerate(files): 134 assert get_file_contents(index) == f.read() 135 136 137def assert_is_active_element(session, element): 138 """Verify that element reference is the active element.""" 139 from_js = session.execute_script("return document.activeElement") 140 141 if element is None: 142 assert from_js is None 143 else: 144 assert_same_element(session, element, from_js) 145 146 147def assert_same_element(session, a, b): 148 """Verify that two element references describe the same element.""" 149 if isinstance(a, dict): 150 assert Element.identifier in a, "Actual value does not describe an element" 151 a_id = a[Element.identifier] 152 elif isinstance(a, Element): 153 a_id = a.id 154 else: 155 raise AssertionError("Actual value is not a dictionary or web element") 156 157 if isinstance(b, dict): 158 assert Element.identifier in b, "Expected value does not describe an element" 159 b_id = b[Element.identifier] 160 elif isinstance(b, Element): 161 b_id = b.id 162 else: 163 raise AssertionError("Expected value is not a dictionary or web element") 164 165 if a_id == b_id: 166 return 167 168 message = ("Expected element references to describe the same element, " + 169 "but they did not.") 170 171 # Attempt to provide more information, accounting for possible errors such 172 # as stale element references or not visible elements. 173 try: 174 a_markup = session.execute_script("return arguments[0].outerHTML;", args=(a,)) 175 b_markup = session.execute_script("return arguments[0].outerHTML;", args=(b,)) 176 message += " Actual: `%s`. Expected: `%s`." % (a_markup, b_markup) 177 except WebDriverException: 178 pass 179 180 raise AssertionError(message) 181 182 183def assert_in_events(session, expected_events): 184 actual_events = session.execute_script("return window.events") 185 for expected_event in expected_events: 186 assert expected_event in actual_events 187 188 189def assert_events_equal(session, expected_events): 190 actual_events = session.execute_script("return window.events") 191 assert actual_events == expected_events 192 193 194def assert_element_has_focus(target_element): 195 session = target_element.session 196 197 active_element = session.execute_script("return document.activeElement") 198 active_tag = active_element.property("localName") 199 target_tag = target_element.property("localName") 200 201 assert active_element == target_element, ( 202 "Focussed element is <%s>, not <%s>" % (active_tag, target_tag)) 203 204 205def assert_move_to_coordinates(point, target, events): 206 for e in events: 207 if e["type"] != "mousemove": 208 assert e["pageX"] == point["x"] 209 assert e["pageY"] == point["y"] 210 assert e["target"] == target 211 212 213def assert_png(screenshot): 214 """Test that screenshot is a Base64 encoded PNG file.""" 215 image = decodebytes(screenshot.encode()) 216 mime_type = imghdr.what("", image) 217 assert mime_type == "png", "Expected image to be PNG, but it was {}".format(mime_type) 218