ドロップダウンprotractorjs 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();

これにより、次のエラーが発生します。

無効または無効な文字列が指定されましたビルド情報:バージョン: '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 Capabilities [{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は関数ではありません。
ジャスティン

251

私にとっては魅力のように働いた

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

それが役に立てば幸い。


2
マイナーなメモ-v0.22のみ(私はコードを今日これに置き換えようとしたところ、アップグレードする必要がありました)
PaulL

これを使用して要素をターゲティングする方法はありますか?状態選択メニューが重複しているなど。
クリストファーマーシャル

11
クリストファーは、ElementFinderあなたが行うことができますので、チェーンことができます:element(by.css('.specific-select')).element(by.cssContainingText('option', 'BeaverBox Testing')).click();
ジョエルKornbluh

6
部分一致を取得できるため、「小」は「超小」と一致します。
TrueWillは、

3
TrueWillのコメントに追加するには:このソリューションの欠点は、2つの同様のオプションがある場合、最後に見つかったオプションを使用することです。これにより、誤った選択に基づいてエラーが発生します。私にとってうまくいったのは、stackoverflow.com / a / 25333326/1945990
Mike W

29

エレガントなアプローチには、他のセレン言語バインディングが標準で提供しているもの(PythonやJavaのクラスなど)と同様の抽象化が含まれますSelect

便利なラッパーを作成して、実装の詳細を内部に隠しましょう。

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、2015年

1
@ミシエル良い点。によって返されたpromiseを明示的に解決したい場合は、必要になる可能性がありますclick()。ありがとう。
alecxe 2015年

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

1
それは私にとって最も正しいです。cssContainingTextでは、目的のフィールドを確実にキャプチャすることはできません。同じ値の2つのselectboxがあると考えてください。+1
YoBre

4
申し訳ありません、BKN01とは何ですか。
Gerfried 2016年

1
@Gerfried BKN01は、ドロップダウンから選択するテキストです。
MilanYadav

@GalBracha申し訳ありませんでした
MilanYadav

BKN01と同じ設定を共有する別のオプションがある場合、それは機能しません。ランダムに拾われます。
zs2020

15

特定のオプションにアクセスするには、nth-child()セレクターを提供する必要があります。

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

これは質問に対する答えを提供しません。批評したり、著者に説明を要求するには、投稿の下にコメントを残してください。
jpw 2013年

@jpwは私の答えが間違っています。それとも間違っている私の答えの定式化ですか?
2013年

質問としての回答の定式化が理由です。正解かどうかわかりません。もしそうなら、あなたはそれをそのように処方すべきです。
jpw 2013年

3
@bekiteうまくいきませんでした。それでもエラーが表示されます提案を試したときにElement Not visible error
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();

angularが保留中の処理を完了するのを待つには、分度器の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(); By(css selector、[value = "3"])のエラーが発生しています
Anuj KC '20

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

問題は、通常の角度選択ボックスで機能するソリューションが、分度器を使用した角度マテリアル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();
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

Droogansのハックで修正されたFirefoxのオプションの選択に問題があります。ここで明示的に触れておきたいのは、誰かの問題を解決できることを願っていますhttps : //github.com/angular/protractor/issues/480

テストがローカルでFirefoxを通過している場合でも、CircleCIやTravisCI、またはCIとデプロイメントに使用しているものでテストが失敗する場合があります。最初からこの問題に気づいていれば、多くの時間を節約できたでしょう。


1

オプション要素を設定するヘルパー:

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

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

ソース-https ://github.com/angular/protractor/issues/600


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

コードをすべて1行でスローすると、ドロップダウンで要素を見つけることができるようです。

この解決策に多くの時間を費やして、これが誰かの助けになることを願っています。


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がリストからの選択とインデックス作成に役立つ特別なロケーターを持っている単純な1行の回答です。

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

このコードは問題を解決する可能性がありますが、これが問題を解決する方法と理由の説明含めると、投稿の品質が向上し、おそらくより多くの投票が得られます。あなたが今尋ねている人だけでなく、あなたが将来の読者のための質問に答えていることを忘れないでください。回答を編集して説明を追加し、適用される制限と前提を示してください。口コミから
ダブルビープ

-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(model name)は、select要素の属性です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.