드롭 다운 protractorjs e2e 테스트에서 옵션을 선택하는 방법


121

각도기를 사용하여 각도 e2e 테스트를 위해 드롭 다운에서 옵션을 선택하려고합니다.

다음은 선택 옵션의 코드 스 니펫입니다.

<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 : 알 수 없음

나는 또한 시도했다 :

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}]

누구 든지이 문제로 나를 도와 주거나 내가 여기서 잘못하고있는 일에 대해 약간의 빛을 던질 수 있습니까?

답변:


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는 함수가 아닙니다.
Justin

251

나를 위해 매력처럼 일 했어

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

도움이 되었기를 바랍니다.


2
사소한 참고 사항-v0.22 만 해당 (오늘 코드를이 코드로 교체하려고했으며이를 얻기 위해 업그레이드해야했습니다)
PaulL

이것을 사용하여 요소를 타겟팅하는 방법이 있습니까? 중복 상태 선택 메뉴를 갖는 것과 같은.
Christopher Marshall

11
Christopher, ElementFinder체인이 가능하므로 다음을 수행 할 수 있습니다.element(by.css('.specific-select')).element(by.cssContainingText('option', 'BeaverBox Testing')).click();
Joel Kornbluh

6
부분 일치를 얻을 수 있으므로 'Small'은 'Extra Small'과 일치합니다.
TrueWill

3
TrueWill의 의견에 추가하려면 :이 솔루션의 단점은 두 개의 유사한 옵션이있는 경우 마지막으로 발견 된 옵션을 사용한다는 것입니다.이 옵션은 잘못된 선택을 기반으로 오류를 발생시킵니다. 나를 위해 일한 것은 stackoverflow.com/a/25333326/1945990
Mike W

29

우아한 접근 방식 은 다른 셀레늄 언어 바인딩이 즉시 제공하는 것과 유사한 추상화를 만드는 것입니다 (예 : SelectPython 또는 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');

다음 주제에서 가져온 솔루션 : 선택-> 옵션 추상화 .


참고로, 기능 요청 생성 : 선택-> 옵션 추상화 .


선택 기능에서 '반품'을 사용하는 이유는 무엇입니까? 그게 필요한가요?
Michiel

1
@Michiel 좋은 지적. 에서 반환 한 약속을 명시 적으로 해결하려는 경우 필요할 수 있습니다 click(). 감사.
alecxe 2015

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

1
그것은 나에게 가장 정확합니다. cssContainingText를 사용하면 원하는 필드를 캡처해야합니다. 같은 값을 가진 두 개의 선택 상자가 있다고 생각하십시오. +1
YoBre 2015 년

4
죄송합니다. BKN01이 무엇인가요?
Gerfried

1
@Gerfried BKN01은 드롭 다운에서 선택하려는 텍스트입니다.
MilanYadav

죄송합니다 @GalBracha 당신에게하지 않았다
MilanYadav

BKN01과 동일한 Prefex를 공유하는 다른 옵션이 있으면 작동하지 않습니다. 무작위로 하나를 선택합니다.
zs2020

15

특정 옵션에 액세스하려면 nth-child () 선택기를 제공해야합니다.

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

이것은 질문에 대한 답을 제공하지 않습니다. 작성자에게 비평이나 설명을 요청하려면 게시물 아래에 댓글을 남겨주세요.
jpw

@jpw는 내 대답이 잘못되었습니다. 아니면 단순히 내 대답의 공식화가 잘못 되었습니까?
bekite

대답을 질문으로 공식화하는 것이 이유입니다. 정답인지 모르겠습니다. 그렇다면 그렇게 공식화해야합니다.
jpw

3
@bekite 내가 당신의 제안을 시도 할 때 me.Still이 요소 표시하지 않음 오류 오류를 얻기를 위해 작동하지 않았다
란잔 Bhambroo을

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()방법을 사용하십시오.
Avi Cherry

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 (); (CSS 선택 [값 = "3"])를 기준으로 에러를 얻고
아누 즈 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 rep 포인트). 또한 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();
루안 응우 엔

여기에 또 다른 접근 방식이 있습니다. mdSelectElement.getAttribute('aria-owns').then( function(val) { let selectMenuContainer = element(by.id(val)); selectMenuContainer.element(by.css('md-option[value="foo"]')).click(); } );
gbruins

1

Firefox에서 옵션을 선택하는 데 문제가 있는데 Droogans의 해킹 수정이 여기에 명시 적으로 언급하고 싶습니다. 누군가 문제를 해결할 수 있기를 바랍니다 : https://github.com/angular/protractor/issues/480 .

테스트가 Firefox로 로컬에서 통과하더라도 CircleCI 또는 TravisCI 또는 CI 및 배포에 사용하는 모든 항목에서 실패하고 있음을 알 수 있습니다. 처음부터이 문제를 인식하면 많은 시간을 절약 할 수있었습니다.)


1

옵션 요소를 설정하는 도우미 :

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


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'섹션에서 함수를 브라우저 인스턴스 의 구성원으로 선언 하므로 모든 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 개의 선택을 선택해야하고 선택이 열려있는 동안 다음 선택을 선택하는 방법에 오버레이가 있습니다. 그렇기 때문에 여전히 작동중인 머티리얼 이펙트에 문제가 발생하지 않도록 500ms를 기다려야합니다.


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

값별로 드롭 다운 옵션을 선택할 수 있습니다. $('#locregion').$('[value="1"]').click();


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 (모델 이름)는 선택 요소의 속성입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.