如何在下拉式Protractor.js e2e测试中选择选项


121

我正在尝试使用量角器从下拉菜单中选择一个选项进行角度e2e测试。

这是select选项的代码片段:

<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();

这给了我以下错误:

指定了无效或非法字符串Build info:版本:'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:未知

我也尝试过:

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'系统信息:操作系统名称:'Mac OS X',操作系统名称:'x86_64',操作系统版本:'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}]

任何人都可以帮助我解决这个问题,或者对我在这里做错的事情有所了解。

Answers:


88

我遇到了类似的问题,最终编写了一个用于选择下拉列表值的辅助函数。

我最终决定可以按选项号进行选择,因此编写了一个方法,该方法采用一个元素和optionNumber,然后选择该optionNumber。如果optionNumber为null,则不选择任何内容(不选择下拉菜单)。

var selectDropdownbyNum = function ( element, optionNum ) {
  if (optionNum){
    var options = element.all(by.tagName('option'))   
      .then(function(options){
        options[optionNum].click();
      });
  }
};

我写了一篇博客文章,如果您需要更多细节,它还介绍了在下拉列表中验证所选选项的文本:http : //technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation/


1
不适用于我,得到了element.findElements不是一个函数。
贾斯汀

251

对我来说就像魅力

element(by.cssContainingText('option', 'BeaverBox Testing')).click();

希望能帮助到你。


2
次要注意事项-仅适用于v0.22(我今天只是用此代码替换了我的代码,并且不得不升级才能得到它)
PaulL 2014年

有没有办法使用此来定位元素?例如具有重复的状态选择菜单。
Christopher Marshall

11
克里斯托弗(Christopher),ElementFinder具有连锁能力,因此您可以执行以下操作:element(by.css('.specific-select')).element(by.cssContainingText('option', 'BeaverBox Testing')).click();
乔尔·科恩布鲁

6
请注意,您可以获得部分匹配,因此“小”将匹配“特小”。
TrueWill

3
要添加到TrueWill的评论中:该解决方案的缺点是,如果您有两个类似的选项,它将使用最后找到的选项-由于选择错误而引发错误。对我有用的
Mike W

29

一种优雅的方法是其抽象化为类似于其他硒语言绑定提供的现成(例如Select,Python或Java中的类)。

让我们做一个方便的包装,并在其中隐藏实现细节:

var SelectWrapper = function(selector) {
    this.webElement = element(selector);
};
SelectWrapper.prototype.getOptions = function() {
    return this.webElement.all(by.tagName('option'));
};
SelectWrapper.prototype.getSelectedOptions = function() {
    return this.webElement.all(by.css('option[selected="selected"]'));
};
SelectWrapper.prototype.selectByValue = function(value) {
    return this.webElement.all(by.css('option[value="' + value + '"]')).click();
};
SelectWrapper.prototype.selectByPartialText = function(text) {
    return this.webElement.all(by.cssContainingText('option', text)).click();   
};
SelectWrapper.prototype.selectByText = function(text) {
    return this.webElement.all(by.xpath('option[.="' + text + '"]')).click();   
};

module.exports = SelectWrapper;

使用示例(请注意它的可读性和易用性):

var SelectWrapper  = require('select-wrapper');
var mySelect = new SelectWrapper(by.id('locregion'));

# select an option by value
mySelect.selectByValue('4');

# select by visible text
mySelect.selectByText('BoxLox');

来自以下主题的解决方案:选择->选项抽象


仅供参考,创建了一个功能请求:选择->选项抽象


为什么在选择的功能中使用“返回”?那有必要吗?
米歇尔2015年

1
@Michiel好点。如果您想显式地解决所返回的诺言,则可能有必要click()。谢谢。
alecxe

20
element(by.model('parent_id')).sendKeys('BKN01');

1
对我来说这是最正确的。使用cssContainingText时,您不能确保捕获所需的字段。试想一下,如果您有两个具有相同值的选择框。+1
YoBre 2015年

4
抱歉,什么是BKN01?
Gerfried

1
@Gerfried BKN01是要从下拉菜单中选择的文本。
米兰雅达夫'16

@GalBracha对不起,您没把握
MilanYadav

如果您有与BKN01共享相同预定义的其他选项,则它将不起作用。随机抽取一个。
zs2020

15

要访问特定选项,您需要提供nth-child()选择器:

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

这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方发表评论。
13年

@jpw是我的答案错误。还是仅仅是我的回答是错的?
bekite

将答案表述为问题是为什么。我不知道这是正确的答案。如果是这样,则应这样制定。
13年

3
@bekite不适用于我。仍然收到错误元素不可见错误,当我尝试您的建议时
Ranjan Bhambroo 2013年

8

这就是我所做的选择。

function switchType(typeName) {
     $('.dropdown').element(By.cssContainingText('option', typeName)).click();
};

5

这是我的做法:

$('select').click();
$('select option=["' + optionInputFromFunction + '"]').click();
// This looks useless but it slows down the click event
// long enough to register a change in Angular.
browser.actions().mouseDown().mouseUp().perform();

要等待角完成未完成的处理,请使用量角器的waitForAngular()方法。
阿维·切里

5

试试这个,它为我工作:

element(by.model('formModel.client'))
    .all(by.tagName('option'))
    .get(120)
    .click();

4

您可以尝试此希望它会起作用

element.all(by.id('locregion')).then(function(selectItem) {
  expect(selectItem[0].getText()).toEqual('Ranjans Mobile Testing')
  selectItem[0].click(); //will click on first item
  selectItem[3].click(); //will click on fourth item
});

4

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

var select = element(by.model('organization.parent_id'));
select.$('[value="1"]').click();

var orderTest = element(by.model('ctrl.supplier.orderTest'))orderTest。$('[value =“ 1”]')。click(); 正在收到错误By(css选择器,[value =“ 3”])
Anuj KC

3

要选择具有唯一ID的项目(选项),例如:

<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();

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的键入。


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 Material md-select和md-option。这个帖子是由另一个发布的,但是对我有用,我还不能评论他的帖子(只有23个代表点)。另外,我清理了一下,而不是用browser.sleep,而是用browser.waitForAngular();。

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

按索引选择选项:

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

1

我已经改进了PaulL编写的解决方案。首先,我修复了与最后一个量角器API兼容的代码。然后,我在Protractor配置文件的“ onPrepare”部分中将该函数声明为浏览器实例的成员,以便可以从任何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();
        });
    };
  },

1

我一直在网上寻找有关如何在模型下拉列表中选择选项的答案,并且我使用了这种组合,这有助于我使用Angular材质。

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

似乎将代码全部扔到一行时,可以在下拉列表中找到该元素。

我花了很多时间来寻求解决方案,希望这对某人有所帮助。


0

我们想在这里使用angularjs材料使用优雅的解决方案,但是它没有用,因为在单击md-select之前,DOM中实际上没有选项/ md-option标记。因此,“优雅”方式对我们不起作用(请注意棱角分明的材料!)这是我们为此所做的,不知道它是否是最好的方式,但现在已经确定了

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

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

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
----------
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')


});


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
static selectDropdownValue(dropDownLocator,dropDownListLocator,dropDownValue){
    let ListVal ='';
    WebLibraryUtils.getElement('xpath',dropDownLocator).click()
      WebLibraryUtils.getElements('xpath',dropDownListLocator).then(function(selectItem){
        if(selectItem.length>0)
        {
            for( let i =0;i<=selectItem.length;i++)
               {
                   if(selectItem[i]==dropDownValue)
                   {
                       console.log(selectItem[i])
                       selectItem[i].click();
                   }
               }            
        }

    })

}

0

我们可以为此创建一个自定义的DropDown类,并添加如下方法:

async selectSingleValue(value: string) {
        await this.element.element(by.xpath('.//option[normalize-space(.)=\'' + value + '\']')).click();
    }

另外,要验证当前选择的值,我们可以:

async getSelectedValues() {
        return await this.element.$('option:checked').getText();
    }

0

下面的示例是最简单的方法。我已经测试并通过了量角器版本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();

  });
});

0

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

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

尽管这段代码可以解决问题,但包括解释如何以及为何解决该问题的说明,确实可以帮助提高您的帖子质量,并可能导致更多的投票。请记住,您将来会为读者回答问题,而不仅仅是现在问的人。请编辑您的答案以添加说明,并指出适用的限制和假设。点评来源
Double-beep

-1

通过CSS属性选择选项

element(by.model("organization.parent_id")).element(by.css("[value='1']")).click();

要么

element(by.css("#locregion")).element(by.css("[value='1']")).click();

其中locregion(id),organization.parent_id(模型名称)是select元素的属性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.