如何在ProtractorJS E2E测试中选择下拉选项

127

我正在尝试使用Protractor为Angular的端到端测试从下拉框中选择选项。

这是选择选项的代码片段:

<select id="locregion" class="create_select ng-pristine ng-invalid ng-invalid-required" required="" ng-disabled="organization.id !== undefined" ng-options="o.id as o.name for o in organizations" ng-model="organization.parent_id">
    <option value="?" selected="selected"></option>
    <option value="0">Ranjans Mobile Testing</option>
    <option value="1">BeaverBox Testing</option>
    <option value="2">BadgerBox</option>
    <option value="3">CritterCase</option>
    <option value="4">BoxLox</option>
    <option value="5">BooBoBum</option>
</select>

我尝试过:

ptor.findElement(protractor.By.css('select option:1')).click();

这给我带来了以下错误:

指定了一个无效或非法的字符串 构建信息:版本:'2.35.0',修订版:'c916b9d',时间:'2013-08-12 15:42:01' 系统信息:os.name:'Mac OS X',os.arch:'x86_64',os.version:'10.9',java.version:'1.6.0_65' 驱动程序信息:driver.version:unknown

我也尝试过:

ptor.findElement(protractor.By.xpath('/html/body/div[2]/div/div[4]/div/div/div/div[3]/ng-include/div/div[2]/div/div/organization-form/form/div[2]/select/option[3]')).click();
这给我带来了以下错误:

ElementNotVisibleError:元素当前不可见,因此无法进行交互
命令持续时间或超时:9毫秒
构建信息:版本:'2.35.0',修订版:'c916b9d',时间:'2013-08-12 15:42:01'
系统信息:os.name:'Mac OS X',os.arch:'x86_64',os.version:'10.9',java.version:'1.6.0_65'
会话ID:bdeb8088-d8ad-0f49-aad9-82201c45c63f
驱动程序信息:org.openqa.selenium.firefox.FirefoxDriver
功能 [{platform=MAC,acceptSslCerts=true,javascriptEnabled=true,browserName=firefox,rotatable=false,locationContextEnabled=true,version=24.0,cssSelectorsEnabled=true,databaseEnabled=true,handlesAlerts=true,browserConnectionEnabled=true,nativeEvents=false,webStorageEnabled=true,applicationCacheEnabled=false,takesScreenshot=true}]


请问有谁能帮我解决这个问题或指点一下我在这里做错了什么。
34个回答

3
我们编写了一个包含3种选项选择方式的库:
selectOption(option: ElementFinder |Locator | string, timeout?: number): Promise<void>

selectOptionByIndex(select: ElementFinder | Locator | string, index: number, timeout?: number): Promise<void>

selectOptionByText(select: ElementFinder | Locator | string, text: string, timeout?: number): Promise<void>

这些函数的额外功能是在执行 select 上的任何操作之前等待元素显示。你可以在npm上找到它:@hetznercloud/protractor-test-helper。同时也提供了TypeScript的类型定义。

3

如何选择具有唯一ID的选项(option)如这里所示:

<select
    ng-model="foo" 
    ng-options="bar as bar.title for bar in bars track by bar.id">
</select>

我正在使用这个:

element(by.css('[value="' + neededBarId+ '"]')).click();

2
也许不是非常优雅,但很高效:
function selectOption(modelSelector, index) {
    for (var i=0; i<index; i++){
        element(by.model(modelSelector)).sendKeys("\uE015");
    }
}

这只是在您想要的选择器上发送按键,我们在这里使用modelSelector,但显然您可以使用任何其他选择器。

然后在我的页面对象模型中:

selectMyOption: function (optionNum) {
       selectOption('myOption', optionNum)
}

并从测试中获得:

myPage.selectMyOption(1);

2

问题在于对于 Angular 来说,解决常规选择框的方案不能够与使用 Protractor 的 Angular Material md-select 和 md-option 配合使用。下面这个方法是由另一个人发布的,但它对我有效,只是我还没有足够的评论权限 (只有23点声望)。此外,我稍微整理了一下,用 browser.waitForAngular() 替代了 browser.sleep。

element.all(by.css('md-select')).each(function (eachElement, index) {
    eachElement.click();                    // select the <select>
    browser.waitForAngular();              // wait for the renderings to take effect
    element(by.css('md-option')).click();   // select the first md-option
    browser.waitForAngular();              // wait for the renderings to take effect
});

我只是使用以下代码: element(by.model('selectModel')).click(); element(by.css('md-option[value="searchOptionValue"]')).click(); - Luan Nguyen
这里有另一种方法:mdSelectElement.getAttribute('aria-owns').then( function(val) { let selectMenuContainer = element(by.id(val)); selectMenuContainer.element(by.css('md-option[value="foo"]')).click(); } ); - gbruins

1

我一直在网上搜寻如何在模型下拉列表中选择选项的答案,我使用了以下组合,这对我在Angular材料方面有所帮助。

element(by.model("ModelName")).click().element(By.xpath('xpathlocation')).click();

看起来,将代码全部放在一行中时,它可以在下拉菜单中找到元素。

为了解决这个问题花费了很多时间,希望这能帮助到某些人。


1
如果以上答案都没有解决您的问题,请尝试以下方法。
使用async/await也可以实现。
用于按文本选择选项。
let textOption = "option2"
await element(by.whichever('YOUR_DROPDOWN_SELECTOR'))
  .getWebElement()
  .findElement(by.xpath(`.//option[text()="${textOption}"]`))
  .click();

或者通过数字。
let optionNumber = 2
await element(by.whichever('YOUR_DROPDOWN_SELECTOR'))
  .getWebElement()
  .findElement(by.xpath(`.//option[${optionNumber}]`))
  .click();

当然,您可能需要修改子选项的xpath。
不要问我为什么,但这是我失去希望后自动化下拉菜单的唯一方法。

更新

实际上有一种情况,即使采用这种方法也无法解决。解决办法有点丑陋,但有效。我只需要选择两次该值。


1
如果下面是给定的下拉菜单 -

            <select ng-model="operator">
            <option value="name">Addition</option>
            <option value="age">Division</option>
            </select>

然后,ProtractorJS 的代码可以是 -

        var operators=element(by.model('operator'));
      operators.$('[value=Addition]').click();

Source-https://github.com/angular/protractor/issues/600


1

在Firefox中选择选项存在问题,Droogans的hack可以解决这个问题,我想在这里明确提到,希望能帮助有需要的人:https://github.com/angular/protractor/issues/480

即使你的测试在本地使用Firefox通过了,但你可能会发现它们在CircleCI、TravisCI或其他用于CI和部署的工具上失败了。从一开始就意识到这个问题会节省我很多时间:)


1

设置选项元素的帮助程序:

selectDropDownByText:function(optionValue) {
            element(by.cssContainingText('option', optionValue)).click(); //optionValue: dropDownOption
        }

1
下面的示例是最简单的方法。我已经在 Protractor 版本 5.4.2 中进行了测试并通过了。
//Drop down selection  using option's visibility text 

 element(by.model('currency')).element(by.css("[value='Dollar']")).click();
 Or use this, it   $ isshort form for  .By.css
  element(by.model('currency')).$('[value="Dollar"]').click();

//To select using index

var select = element(by.id('userSelect'));
select.$('[value="1"]').click(); // To select using the index .$ means a shortcut to .By.css

完整代码
describe('Protractor Demo App', function() {

  it('should have a title', function() {

     browser.driver.get('http://www.way2automation.com/angularjs-protractor/banking/#/');
    expect(browser.getTitle()).toEqual('Protractor practice website - Banking App');
    element(by.buttonText('Bank Manager Login')).click();
    element(by.buttonText('Open Account')).click();

    //Drop down selection  using option's visibility text 
  element(by.model('currency')).element(by.css("[value='Dollar']")).click();

    //This is a short form. $ in short form for  .By.css
    // element(by.model('currency')).$('[value="Dollar"]').click();

    //To select using index
    var select = element(by.id('userSelect'));
    select.$('[value="1"]').click(); // To select using the index .$ means a shortcut to .By.css
    element(by.buttonText("Process")).click();
    browser.sleep(7500);// wait in miliseconds
    browser.switchTo().alert().accept();

  });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接