"""Tests for dom.* commands (require an http/https active tab).""" def test_dom_query_body(browser, http_tab): browser("tabs.active", {"tabId": http_tab["id"]}) elements = browser("dom.query", {"selector": "body"}) assert isinstance(elements, list) assert len(elements) == 1 assert elements[0]["tag"] == "body" def test_dom_query_multiple(browser, http_tab): browser("tabs.active", {"tabId": http_tab["id"]}) # Every HTML page has at least one element elements = browser("dom.query", {"selector": "*"}) assert isinstance(elements, list) assert len(elements) > 1 def test_dom_query_no_match(browser, http_tab): browser("tabs.active", {"tabId": http_tab["id"]}) elements = browser("dom.query", {"selector": "#zzz_no_such_element_zzz"}) assert isinstance(elements, list) assert len(elements) == 0 def test_dom_exists_true(browser, http_tab): browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.exists", {"selector": "html"}) assert result is True def test_dom_exists_false(browser, http_tab): browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.exists", {"selector": "#zzz_no_such_element_zzz"}) assert result is False def test_dom_text_body(browser, http_tab): browser("tabs.active", {"tabId": http_tab["id"]}) texts = browser("dom.text", {"selector": "body"}) assert isinstance(texts, list) assert len(texts) > 0 assert isinstance(texts[0], str) assert len(texts[0]) > 0 def test_dom_attr_returns_list(browser, http_tab): browser("tabs.active", {"tabId": http_tab["id"]}) # Get href of all anchor tags — page may or may not have any hrefs = browser("dom.attr", {"selector": "a", "attr": "href"}) assert isinstance(hrefs, list) def test_dom_attr_html_lang(browser, http_tab): browser("tabs.active", {"tabId": http_tab["id"]}) langs = browser("dom.attr", {"selector": "html", "attr": "lang"}) assert isinstance(langs, list) # html element exists so we get exactly one entry (may be empty string if no lang attr) assert len(langs) <= 1 # --------------------------------------------------------------------------- # dom.eval # --------------------------------------------------------------------------- def test_dom_eval_returns_string(browser, http_tab): """Evaluating document.title returns the page title as a string.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.eval", {"code": "document.title", "tabId": http_tab["id"]}) assert isinstance(result, str) def test_dom_eval_arithmetic(browser, http_tab): """Evaluating a JS expression returns the computed value.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.eval", {"code": "2 + 2", "tabId": http_tab["id"]}) assert result == 4 def test_dom_eval_returns_null_for_void(browser, http_tab): """Evaluating a void expression returns None.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.eval", {"code": "void 0", "tabId": http_tab["id"]}) assert result is None def test_dom_eval_returns_dict(browser, http_tab): """Evaluating an object expression returns a dict.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.eval", {"code": "({a: 1, b: 2})", "tabId": http_tab["id"]}) assert isinstance(result, dict) assert result.get("a") == 1 assert result.get("b") == 2 def test_dom_eval_dom_read(browser, http_tab): """Can read a property of a DOM element via eval.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.eval", {"code": "document.querySelector('h1') ? document.querySelector('h1').textContent : null", "tabId": http_tab["id"]}) # result is either a string (h1 text) or None — both are valid assert result is None or isinstance(result, str) # --------------------------------------------------------------------------- # dom.scroll # --------------------------------------------------------------------------- def test_dom_scroll_to_coordinates(browser, http_tab): """Scrolling to (x, y) coordinates does not raise.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.scroll", {"x": 0, "y": 0}) assert result is None or isinstance(result, (dict, bool)) def test_dom_scroll_to_selector(browser, http_tab): """Scrolling to an existing selector does not raise.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.scroll", {"selector": "body"}) assert result is None or isinstance(result, (dict, bool)) # --------------------------------------------------------------------------- # dom.wait_for # --------------------------------------------------------------------------- def test_dom_wait_for_existing_element(browser, http_tab): """wait_for an element that already exists returns quickly.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.wait_for", { "selector": "html", "timeout": 5000, "visible": False, "hidden": False, "tabId": http_tab["id"], }) # Returns None or a dict on success assert result is None or isinstance(result, dict) def test_dom_wait_for_visible(browser, http_tab): """wait_for visible=True on a visible element succeeds.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.wait_for", { "selector": "body", "timeout": 5000, "visible": True, "hidden": False, "tabId": http_tab["id"], }) assert result is None or isinstance(result, dict) # --------------------------------------------------------------------------- # dom.focus # --------------------------------------------------------------------------- def test_dom_focus_element(browser, http_tab): """Focusing an existing element does not raise.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.focus", {"selector": "body"}) assert result is None or isinstance(result, (dict, bool)) # --------------------------------------------------------------------------- # dom.hover # --------------------------------------------------------------------------- def test_dom_hover_element(browser, http_tab): """Hovering over an existing element does not raise.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.hover", {"selector": "body"}) assert result is None or isinstance(result, (dict, bool)) # --------------------------------------------------------------------------- # dom.type / dom.clear (use a data: URL tab with an ) # --------------------------------------------------------------------------- def test_dom_type_into_input(browser, http_tab): """Type text into an injected input field and read it back via eval.""" browser("tabs.active", {"tabId": http_tab["id"]}) # Inject a fresh input element with a unique id input_id = "__pytest_type_input" browser("dom.eval", { "code": f"(function(){{ var e=document.getElementById('{input_id}'); if(!e){{e=document.createElement('input');e.id='{input_id}';e.type='text';document.body.appendChild(e);}} return true; }})()", "tabId": http_tab["id"], }) browser("dom.type", {"selector": f"#{input_id}", "text": "hello"}) value = browser("dom.eval", {"code": f"document.getElementById('{input_id}').value", "tabId": http_tab["id"]}) assert value == "hello" def test_dom_clear_input(browser, http_tab): """Clear an input field sets its value to empty string.""" browser("tabs.active", {"tabId": http_tab["id"]}) input_id = "__pytest_clear_input" browser("dom.eval", { "code": f"(function(){{ var e=document.getElementById('{input_id}'); if(!e){{e=document.createElement('input');e.id='{input_id}';e.type='text';document.body.appendChild(e);}} e.value='prefilled'; return true; }})()", "tabId": http_tab["id"], }) browser("dom.clear", {"selector": f"#{input_id}"}) value = browser("dom.eval", {"code": f"document.getElementById('{input_id}').value", "tabId": http_tab["id"]}) assert value == "" # --------------------------------------------------------------------------- # dom.key # --------------------------------------------------------------------------- def test_dom_key_event_does_not_raise(browser, http_tab): """Sending a key event to the body does not raise.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.key", {"key": "Tab"}) assert result is None or isinstance(result, (dict, bool)) def test_dom_key_with_selector(browser, http_tab): """Sending a key event to a specific selector does not raise.""" browser("tabs.active", {"tabId": http_tab["id"]}) result = browser("dom.key", {"key": "Escape", "selector": "body"}) assert result is None or isinstance(result, (dict, bool)) # --------------------------------------------------------------------------- # dom.select (requires a value changes it and it can be read back.""" browser("tabs.active", {"tabId": http_tab["id"]}) sel_id = "__pytest_select" browser("dom.eval", { "code": ( f"(function(){{" f" var s=document.getElementById('{sel_id}');" f" if(!s){{" f" s=document.createElement('select');s.id='{sel_id}';" f" ['a','b','c'].forEach(function(v){{var o=document.createElement('option');o.value=v;o.text=v;s.appendChild(o);}});" f" document.body.appendChild(s);" f" }} return true;" f"}})()" ), "tabId": http_tab["id"], }) browser("dom.select", {"selector": f"#{sel_id}", "value": "b"}) value = browser("dom.eval", {"code": f"document.getElementById('{sel_id}').value", "tabId": http_tab["id"]}) assert value == "b" # --------------------------------------------------------------------------- # dom.check / dom.uncheck # --------------------------------------------------------------------------- def test_dom_check_and_uncheck(browser, http_tab): """Checking and unchecking a checkbox toggles its checked state.""" browser("tabs.active", {"tabId": http_tab["id"]}) cb_id = "__pytest_checkbox" browser("dom.eval", { "code": ( f"(function(){{" f" var c=document.getElementById('{cb_id}');" f" if(!c){{" f" c=document.createElement('input');c.id='{cb_id}';c.type='checkbox';" f" document.body.appendChild(c);" f" }} c.checked=false; return true;" f"}})()" ), "tabId": http_tab["id"], }) browser("dom.check", {"selector": f"#{cb_id}"}) checked = browser("dom.eval", {"code": f"document.getElementById('{cb_id}').checked", "tabId": http_tab["id"]}) assert checked is True browser("dom.uncheck", {"selector": f"#{cb_id}"}) checked = browser("dom.eval", {"code": f"document.getElementById('{cb_id}').checked", "tabId": http_tab["id"]}) assert checked is False