9aad012bdc
- Add mocked Click CLI tests across DOM, cookies, page, storage, perf, navigation, tabs, groups, sessions, and windows commands. - Cover integration paths for cookies, page info, performance profiles, and web storage commands. - Extend DOM integration coverage for eval, scrolling, waiting, focus, hover, typing, selection, keyboard, and checkbox interactions. - Add native host unit coverage for message framing, socket helpers, paging guards, timeouts, and profile alias resolution.
268 lines
11 KiB
Python
268 lines
11 KiB
Python
"""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 <input>)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
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 <select> element)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def test_dom_select_dropdown(browser, http_tab):
|
|
"""Setting a <select> 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
|