检测何时使用 Selenium 打开 jquery-ui 自动完成弹出窗口

Detecting when a jquery-ui autocomplete pops open with Selenium

我正在使用 selenium/python 对连接到本地 运行 集线器的远程网络驱动程序建模工作流。

该工作流包括将一些文本输入搜索自动完成并等待它弹出并显示结果。

我得到的最接近的是:

search_field.send_keys("Search Term")
WebDriverWait(browser, 2).until(
    expected_conditions.visibility_of_element_located((By.CSS_SELECTOR, 'ul.ui-autocomplete')),
    "Autocomplete didn't pop up"
)

这让我超时,尽管我已经使用浏览器的 DOM 检查器验证 ul.ui-autocomplete 存在,并且我可以看到自动完成在 Selenium 放弃后仍然在浏览器中明显打开。

我的方法总体上是错误的,还是我只是遗漏了一个 API 细节?

日志输出:

DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element/28/value {"sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "id": "28", "value": ["S", "e", "a", "r", "c", "h", " ", "T", "e", "r", "m"]}
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element {"using": "css selector", "sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "value": "ul.ui-autocomplete"}
[01/Oct/2015 16:13:06]"GET /myapp/search/?q=Search%20Term HTTP/1.1" 200 136
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:GET http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element/29/displayed {"sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "id": "29"}
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element {"using": "css selector", "sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "value": "ul.ui-autocomplete"}
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:GET http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element/29/displayed {"sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "id": "29"}
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element {"using": "css selector", "sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "value": "ul.ui-autocomplete"}
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:GET http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element/29/displayed {"sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "id": "29"}
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element {"using": "css selector", "sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "value": "ul.ui-autocomplete"}
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:GET http://127.0.0.1:4444/wd/hub/session/fa48f475-6836-448e-a00a-e04808477fb0/element/29/displayed {"sessionId": "fa48f475-6836-448e-a00a-e04808477fb0", "id": "29"}
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
Traceback (most recent call last):
  File "runtests.py", line 237, in <module>
    main()
  File "runtests.py", line 231, in main
    searchTest(browser)
  File "runtests.py", line 214, in createHandout
    Autocomplete didn't pop up
  File "/Users/beha/VEs/product-venv/lib/python2.7/site-packages/selenium/webdriver/support/wait.py", line 80, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: Autocomplete didn't pop up

也许您可以直接检查元素的属性?

查找在显示自动完成元素时更改了哪个属性 (visibility/enabled/display),然后在您的 WebDriverWait.

中使用它

的评论太长了,但 terle 将我推向了大致正确的方向。这是干什么的:

def selectFromAutocompleteField(browser, search_field, term):
    search_field.send_keys(term)
    WebDriverWait(browser, 2).until(
        firstElementWithCssAttribute('ul.ui-autocomplete', 'display', 'block')
    )
    search_field.send_keys(Keys.DOWN + Keys.RETURN)

def firstElementWithCssAttribute(css, attribute, content):
    def _withCssAttr(browser):
        for elem in browser.find_elements_by_css_selector(css):
            if elem and elem.value_of_css_property(attribute) == content:
                return elem
            else:
                continue
        return None

    return _withCssAttr

循环构造效率低下的原因是 jQuery UI 自动完成在使用过程中创建了两个不同的 ul.ui-autocomplete;第一个只会在第一次使用时使用,因此必须对所有这些进行轮询,然后再找到第一个可见的。

Selenium 始终 returns 第一项匹配选择 => 在单个 find_element 之后继续 display:block 只工作一次,因此额外的循环构造。

为什么 Selenium 的直接可见性检查不适用于 Safari(甚至一次,当只有一个 ul 存在时)是一个令人失望的谜团——但对于输入 clear() 也可以这样说.