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