使用Selenium WebDriver ExecuteScript命令模仿jQuery自动完成

时间:2012-02-14 23:27:53

标签: c# jquery webdriver jquery-autocomplete selenium-webdriver

注意:

要回答这个问题,你不应该对Selenium或WebDriver有任何了解,只需知道jQuery知识。那是我没有足够知识的地方 - 正是为什么我问这个问题。 :-)如果您还没有听说过Selenium WebDriver,它只是一种从代码中自动化您的网站或Web应用程序的方法(我在我的示例中使用了C#客户端驱动程序)。

另请注意,我的FirefoxDriver对象已启用本机事件

环境:

以下是您在开始输入时在输入字段自动填充中键入的HTML和JavaScript文本片段。选择值时,它会根据输入到输入字段中的记录名称设置一个隐藏字段,其中包含所选值的id。我的目标是通过调用ExecuteScript方法调用一些jQuery代码来模仿WebDriver中的自动完成行为。但由于我知道我们在WebDriver中尝试匹配的确切值,我想模仿最终用户使用此值键入字段的内容。如何才能做到这一点?

如果我无法正常工作,我的答案就是直接用id设置隐藏字段。但我宁愿把文本传递给我,所以我实际上可以模仿最终用户正在做的事情。 WebDriver脚本只会输入部分或全部文本(值在ac_variation_id中设置),并且不会通过AJAX检索记录ID(值在variation_id隐藏字段中设置)。下面,我正在设置两个值。但是,我只想要一个获取id并设置id的jQuery脚本,或者模仿在输入中键入值。

所以我必须解决两种方式之一:
- 让WebDriver模仿自动完成100%
- 让WebDriver调用一个JavaScript脚本(jQuery AJAX调用),除了键入值之外,它执行页面执行的所有操作,以便使用为所选选项返回的id设置隐藏字段

我只是不知道该怎么办。

示例jQuery脚本设置带有id的隐藏字段和带有文本的输入字段:

Element.SetValueById(driver, "variation_id", discount.Variation);  // set input field with text
Element.SetValueById(driver, "ac_variation_id", "123");  // set hidden field with id

        public static void SetValueById(IWebDriver driver, string tagId, string newValue)
        {
            IJavaScriptExecutor js = driver as IJavaScriptExecutor;
            js.ExecuteScript("$('#" + tagId + "').val('" + newValue + "')");
        }

自动填充功能的HTML代码和JavaScript代码:

<link rel="stylesheet" href="http://localhost/admin/css/vanilla/jquery.ui.autocomplete.css" media="screen" type="text/css" />

<script type='text/javascript' src="http://localhost/admin/js/vanilla/jquery-ui-1.7.1.custom.min.js"></script>
<script type="text/javascript" src="http://localhost/admin/js/vanilla/jquery.ui.autocomplete.ext.js"></script>
<script type="text/javascript" src="http://localhost/admin/js/vanilla/jquery.ui.autocomplete.js"></script>

<input type="text"  name="ac_variation_id" id="ac_variation_id" value="" class="autocomplete" autocomplete="off" />
<button type="button" value="clear" name="cl_variation_id" id="cl_variation_id"  onclick="$('#variation_id').val('');$('#ac_variation_id').val('');"  >clear</button>
<input type="hidden" name="variation_id" id="variation_id" value="" />

<script>
    $('#ac_variation_id').autocomplete({ 
        ajax: 'http://localhost/admin/discount/ajax-auto-complete/variation',
        match: function(typed) { 
                return this.name;//.match(new RegExp("^"+typed, "i")); had to comment that out to be able to type integration_id and display name 
        },
        insertText: function(entity) { 
                return entity.name +' '+ (( entity.integration_id == undefined ) ? '' : entity.integration_id);
        }
    }).bind("activate.autocomplete",function(e, entity){

        var id = '#'+($(this).attr('id').substring(3));//remove ac_ prefix
        $(id).val( entity.id );
    });
</script>

在输入字段中输入文字后自动填充查找值的屏幕截图:

enter image description here

3 个答案:

答案 0 :(得分:1)

使用自动完成小部件可以测试两件事:1)在文本字段中键入内容,2)从自动完成列表中选择一个项目。

这些答案都是红宝石,但我怀疑有相应的C#版本

键入文本字段

search_term = "stackoverflow.com"

input = find('#q')
input.click

# this is the same as input.set(search_term[0..5]) I believe
search_term[0..5].chars.each do |key|
    input.native.send_key(key)
end

从自动填充列表中选择项目(按项目文字)

search_term = "stackoverflow.com"
selector = ".ui-menu-item a:contains(\"#{@search_term}\")"
page.execute_script " $('#{selector}').trigger(\"mouseenter\").click();"

# I have 4 auto completes on my page, so I just wait until they all gone
wait_until do
    autocompletes = all(:css, '.ui-autocomplete')
    autocompletes.inject(true) { |x,autocomplete| x && !autocomplete.visible? }
end

答案 1 :(得分:0)

我无法模仿自动完成并选择选项,因此我调用JSON GET请求来获取隐藏字段的id,并在找到的第一个匹配项上设置隐藏字段(万一有多个)。

Element.SetHiddenFieldIdViaAutoCompleteJSON(driver, "/admin/discount/ajax-auto-complete/variation", "val", discount.Variation, "id", "variation_id");

public static void SetHiddenFieldIdViaAutoCompleteJSON(IWebDriver driver, string requestPage, string queryParam, string queryParamValue, string jsonObjectProperty, string hiddenFieldId)
{
    IJavaScriptExecutor js = driver as IJavaScriptExecutor;
    js.ExecuteScript("$.ajax({ url: '" + Config.SITE_URL + requestPage + "',data:{'" + queryParam + "':'" + queryParamValue + "'},dataType:'json',type: 'GET',contentType: 'application/json',success: function(jsonObject) { $('#" + hiddenFieldId + "').val(jsonObject[0]." + jsonObjectProperty + "); } });");
}

答案 2 :(得分:0)

使用Selenuim IDE并导出到Java代码,我将结果调整为以下功能,以便我可以选择要更改哪个Autocomplete Combobox。 (这也是'Base'类,我的所有PageObjets都扩展了。

public BasicPage selectComboBox(int buttonIndex, String selection) {
  driver.findElement(By.xpath("(//button[@type='button'])[" + buttonIndex + "]")).click();
  driver.findElement(By.xpath("//html/body/ul/li/a[. = \"" + selection + "\"]")).click();

  // delay till the selected element is visible
  WebElement duh = (new WebDriverWait(driver, 10)).until( visibilityOfElementLocated(By.xpath("(//button[@type='button'])[" + buttonIndex +"]" )) ) ;     

  return this;
}