如何在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个回答

1

按索引选择选项:

var selectDropdownElement= element(by.id('select-dropdown'));
selectDropdownElement.all(by.tagName('option'))
      .then(function (options) {
          options[0].click();
      });

1

我对PaulL的解决方案进行了一些改进。 首先,我修复了代码以与最新的Protractor API兼容。然后,我在Protractor配置文件的'onPrepare'部分中声明该函数为browser实例的成员,因此它可以在任何e2e规范中引用。

  onPrepare: function() {
    browser._selectDropdownbyNum = function (element, optionNum) {
      /* A helper function to select in a dropdown control an option
      * with specified number.
      */
      return element.all(by.tagName('option')).then(
        function(options) {
          options[optionNum].click();
        });
    };
  },

0

设置选项元素的另一种方式:

var setOption = function(optionToSelect) {

    var select = element(by.id('locregion'));
    select.click();
    select.all(by.tagName('option')).filter(function(elem, index) {
        return elem.getText().then(function(text) {
            return text === optionToSelect;
        });
    }).then(function(filteredElements){
        filteredElements[0].click();
    });
};

// using the function
setOption('BeaverBox Testing');

0

我们本来想使用AngularJS Material中优雅的解决方案,但实际上在md-select未被点击之前,DOM中根本没有任何选项/md-option标签。因此,这种“优雅”的方法对我们不起作用(注意Angular Material!)这是我们为此所做的事情,不知道它是否是最好的方法,但它绝对可以正常工作。

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

我们需要选择4个选项,当选项打开时,有一个遮罩挡住了下一个选项的选择,这就是为什么我们需要等待500毫秒来确保我们不会遇到材料效果仍在进行中的麻烦。

0

以下是如何通过选项值或索引来完成。这个示例有些粗糙,但它展示了如何实现你想要的功能:

HTML:

<mat-form-field id="your-id">
    <mat-select>
        <mat-option [value]="1">1</mat-option>
        <mat-option [value]="2">2</mat-option>
    </mat-select>
</mat-form-field>

ts:

function selectOptionByOptionValue(selectFormFieldElementId, valueToFind) {

  const formField = element(by.id(selectFormFieldElementId));
  formField.click().then(() => {

    formField.element(by.tagName('mat-select'))
      .getAttribute('aria-owns').then((optionIdsString: string) => {
        const optionIds = optionIdsString.split(' ');    

        for (let optionId of optionIds) {
          const option = element(by.id(optionId));
          option.getText().then((text) => {
            if (text === valueToFind) {
              option.click();
            }
          });
        }
      });
  });
}

function selectOptionByOptionIndex(selectFormFieldElementId, index) {

  const formField = element(by.id(selectFormFieldElementId));
  formField.click().then(() => {

    formField.element(by.tagName('mat-select'))
      .getAttribute('aria-owns').then((optionIdsString: string) => {
        const optionIds = optionIdsString.split(' ');

        const optionId = optionIds[index];
        const option = element(by.id(optionId));
        option.click();
      });
  });
}

selectOptionByOptionValue('your-id', '1'); //selects first option
selectOptionByOptionIndex('your-id', 1); //selects second option

0

我发现使用索引选择选项的最简单方法是:

var selectDropdownElement = await element(by.xpath("Some Xpath"));
                await selectDropdownElement.all(by.tagName('option')).then(function (options) {
                        options[index].click();
                });

'index' 是您想要点击的选项号码


0

这对于Angular Material运作良好。

element(by.css("mat-select[formcontrolname=myMatSelect]")).sendKeys(valueToSet);

如果在您的选项中不存在"valueToSet",则不应设置它。


0
您可以通过值选择下拉选项: $('#locregion').$('[value="1"]').click();

0

这是一个简单的一行答案,其中Angular有特殊的定位器,可以帮助从列表中选择和索引。

element.all(by.options('o.id as o.name for o in organizations')).get(Index).click()

虽然这段代码可能解决了问题,但是加上解释说明(包括如何以及为什么解决该问题)真的会帮助提高您的帖子质量,并可能导致更多的投票赞同。请记住,你正在为未来的读者回答问题,而不仅仅是现在提问的人。请[编辑]您的答案,添加解释并指出适用的限制和假设。来自审核 - double-beep

0
----------
element.all(by.id('locregion')).then(function(Item)
{
 // Item[x] = > // x is [0,1,2,3]element you want to click
  Item[0].click(); //first item

  Item[3].click();     // fourth item
  expect(Item[0].getText()).toEqual('Ranjans Mobile Testing')


});

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