Açılır açıölçer js e2e testlerinde seçenek nasıl seçilir


121

Açıölçer kullanarak açısal e2e testleri için açılır listeden bir seçenek belirlemeye çalışıyorum.

İşte seçme seçeneğinin kod pasajı:

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

Denedim:

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

Bu bana şu hatayı veriyor:

Geçersiz veya geçersiz bir dize belirlendi Derleme bilgisi: sürüm: '2.35.0', revizyon: 'c916b9d', saat: '2013-08-12 15:42:01' Sistem bilgisi: os.name: 'Mac OS X' , os.arch: 'x86_64', os.version: '10 .9 ', java.version:' 1.6.0_65 'Sürücü bilgisi: sürücü.version: bilinmiyor

Ben de denedim:

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

Bu bana şu hatayı veriyor:

ElementNotVisibleError: Öğe şu anda görünür değil ve bu nedenle Komut süresi veya zaman aşımı ile etkileşime girmeyebilir: 9 milisaniye Yapı bilgisi: sürüm: '2.35.0', revizyon: 'c916b9d', saat: '2013-08-12 15:42: 01 'Sistem bilgisi: os.name:' Mac OS X ', os.arch:' x86_64 ', os.version: '10 .9', java.version: '1.6.0_65' Oturum Kimliği: bdeb8088-d8ad-0f49-aad9 -82201c45c63f Sürücü bilgisi: org.openqa.selenium.firefox.FirefoxDriver Capabilities [{platform = MAC, acceptSslCerts = true, javascriptEnabled = true, browserName = firefox, rotatable = false, locationContextEnabled = true, version = 24.0, cssSelectorsEnabled = true, cssSelectorsEnabled = true, handlesAlerts = true, browserConnectionEnabled = true, nativeEvents = false, webStorageEnabled = true, applicationCacheEnabled = false, takesScreenshot = true}]

Biri lütfen bu problemde bana yardım edebilir veya burada yanlış yaptığım şeye ışık tutabilir mi?

Yanıtlar:


88

Benzer bir sorun yaşadım ve sonunda açılır değerleri seçen yardımcı bir işlev yazdım.

Sonunda seçenek numarasına göre seçim yapmakta iyi olduğuma karar verdim ve bu nedenle bir eleman ve seçenekNumarası alan ve bu seçenekNumarası'nı seçen bir yöntem yazdım. OptionNumber null ise hiçbir şey seçmez (açılır menüyü seçmeden bırakır).

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

Daha fazla ayrıntı istiyorsanız bir blog yazısı yazdım, ayrıca bir açılır menüde seçilen seçeneğin metninin doğrulanmasını da kapsar: http://technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation/


1
Benim için işe yaramadı, got element.findElements bir fonksiyon değil.
Justin

251

Benim için bir cazibe gibi çalıştı

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

Umarım yardımcı olur.


2
Küçük not - yalnızca v0.22 (kodumu bugün bununla değiştirmeye gittim ve onu almak için yükseltmek zorunda kaldım)
PaulL

Bunu kullanarak öğeleri hedeflemenin bir yolu var mı? Yinelenen Durum seçme menülerine sahip olmak gibi.
Christopher Marshall

11
Christopher, ElementFinderzincirleme yeteneğine sahiptir, yani şunları yapabilirsiniz:element(by.css('.specific-select')).element(by.cssContainingText('option', 'BeaverBox Testing')).click();
Joel Kornbluh

6
Kısmi eşleşmeler alabileceğinizi unutmayın, bu nedenle 'Küçük', 'Ekstra Küçük' ile eşleşir.
TrueWill

3
TrueWill'in yorumuna eklemek gerekirse: Bu çözümün kötü tarafı, iki benzer seçeneğiniz varsa, son bulunan seçeneği kullanacak olmasıdır - bu da yanlış seçime bağlı olarak hataları ortaya çıkarır. Benim için işe
Mike W

29

Zarif bir yaklaşım , diğer selenyum dil bağlamalarının kullanıma hazır olarak sunduklarına benzer bir soyutlama yapmayı içerir (örneğin Select, Python veya Java'da sınıf).

Kullanışlı bir sarmalayıcı yapalım ve uygulama ayrıntılarını içinde gizleyelim:

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;

Kullanım örneği (ne kadar okunabilir ve kullanımı kolay olduğuna dikkat edin):

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

Aşağıdaki konudan alınan çözüm: Seç -> seçenek soyutlama .


Bilginize, bir özellik isteği yarattı: Seç -> seçenek soyutlaması .


Seçili işlevlerde neden 'iade' kullanıyorsunuz? Bu gerekli mi?
Michiel

1
@Michiel iyi nokta. Tarafından verilen sözü açıkça çözmek istiyorsanız gerekli olabilir click(). Teşekkürler.
alecxe

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

1
Benim için en doğrusu bu. CssContainingText ile istediğiniz alanı yakaladığınızdan emin değilsiniz. Aynı değerlere sahip 2 seçme kutunuz olup olmadığını düşünün. +1
YoBre

4
Pardon, BKN01 nedir?
Gerfried

1
@Gerfried BKN01, açılır menüden seçmek istediğiniz metindir.
MilanYadav

@GalBracha Üzgünüm seni
anlamadı

BKN01 ile aynı prefeksi paylaşan başka bir seçeneğiniz varsa, çalışmayacaktır. Rastgele bir tane alınacak.
zs2020

15

Belirli bir seçeneğe erişmek için nth-child () seçiciyi sağlamanız gerekir:

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

Bu soruya bir cevap vermiyor. Bir yazarı eleştirmek veya açıklama istemek için yazının altına bir yorum bırakın.
jpw

@jpw cevabım yanlış. yoksa yanlış olan cevabımın basitçe formülasyonu mu?
bekite

Bir cevabın soru olarak formüle edilmesi nedenidir. Doğru cevap mı bilmiyorum. Eğer öyleyse, onu bu şekilde formüle etmelisin.
jpw

3
@bekite Benim için işe yaramadı. Hala önerinizi denediğimde Öğe Görünmez hata alıyorum
Ranjan Bhambroo

8

Ben seçimimi böyle yaptım.

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

5

İşte bunu nasıl yaptım:

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

Açının bekleyen işlemi bitirmesini beklemek için iletki waitForAngular()yöntemini kullanın .
Avi Kiraz

5

Bunu dene, benim için çalışıyor:

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

4

Bunu deneyebilirsin, işe yarayacak

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

Bir seçenek öğesi ayarlamanın başka bir yolu:

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

var orderTest = eleman (by.model ('ctrl.supplier.orderTest')) orderTest. $ ('[değer = "1"]'). tıklayın (); Hata alıyorum (css seçici, [value = "3"])
Anuj KC

3

Buradaki gibi benzersiz kimliklere sahip öğeleri (seçenekler) seçmek için:

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

Bunu kullanıyorum:

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

3

Bir seçenek belirlemenin 3 yolunu içeren bir kitaplık yazdık:

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>

Bu işlevlerin ek özelliği, herhangi bir işlem yapılmadan önce öğenin görüntülenmesini beklemeleridir. select gerçekleştirilmeden .

Bunu npm @ hetznercloud / protractor-test-helper'da bulabilirsiniz . TypeScript için yazımlar da sağlanmıştır.


2

Belki süper zarif değil ama verimli:

function selectOption(modelSelector, index) {
    for (var i=0; i<index; i++){
        element(by.model(modelSelector)).sendKeys("\uE015");
    }
}

Bu sadece istediğiniz seçime anahtarı gönderir, bizim durumumuzda modelSelector kullanıyoruz ama tabii ki başka herhangi bir seçiciyi de kullanabilirsiniz.

Sonra sayfa nesne modelimde:

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

Ve testten:

myPage.selectMyOption(1);

2

Sorun, normal açısal seçim kutularında çalışan çözümlerin Açı Malzemesi md-select ve açıölçer kullanan md-seçeneği ile çalışmamasıdır. Bu bir başkası tarafından yayınlandı, ancak benim için işe yaradı ve gönderisine henüz yorum yapamıyorum (yalnızca 23 temsilci puanı). Ayrıca browser.sleep yerine biraz temizledim, 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
});

Sadece şunu kullanıyorum:element(by.model('selectModel')).click(); element(by.css('md-option[value="searchOptionValue"]')).click();
Luan Nguyen

İşte başka bir yaklaşım: 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'ta seçeneklerin seçilmesiyle ilgili, Droogans'ın burada açıkça bahsetmek istediğim hack düzeltmeleriyle ilgili bir sorun var, birinin sorun çıkarmayacağını umuyorum: https://github.com/angular/protractor/issues/480 .

Testleriniz yerel olarak Firefox ile geçse bile, CircleCI veya TravisCI'de veya CI ve dağıtım için kullandığınız her neyse, başarısız olduklarını görebilirsiniz. Bu sorunun en başından farkında olmak bana çok zaman kazandırırdı :)


1

Bir seçenek öğesini ayarlamak için yardımcı:

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


1

Dizine göre seçeneği seçin:

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

1

PaulL tarafından yazılan çözümü biraz geliştirdim. Öncelikle kodu son Protractor API ile uyumlu olacak şekilde düzelttim. Ve sonra, Protractor yapılandırma dosyasının 'onPrepare' bölümündeki işlevi tarayıcı örneğinin bir üyesi olarak ilan ediyorum , böylece herhangi bir e2e spesifikasyonundan başvurulabilir.

  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

Bir model açılır menüsünde bir seçeneğin nasıl seçileceğine dair bir cevap için ağda geziniyordum ve Angular malzemeyle bana yardımcı olan bu kombinasyonu kullandım.

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

Görünüşe göre kodu tek bir satıra atarken, açılır menüde öğeyi bulabilir.

Bu çözüm için çok zaman aldı, umarım bu birisine yardımcı olur.


0

Açısaljs materyalini kullanarak zarif çözümü orada kullanmak istedik, ancak işe yaramadı çünkü md-select tıklanana kadar DOM'da aslında hiçbir option / md-option etiketi yoktu. Yani "zarif" yol bizim için işe yaramadı (köşeli malzemeye dikkat edin!) İşte bunun yerine yaptığımız şey, bunun en iyi yolu mu bilmiyorum ama kesinlikle işe yarıyor

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 seçimin seçilmesi gerekiyordu ve seçim açıkken, sonraki seçimi seçme yolunda bir kaplama var. işte bu yüzden, hala aktif olan maddi efektlerle başımızı belaya sokmamak için 500 ms beklememiz gerekiyor.


0

Bir seçenek öğesi ayarlamanın başka bir yolu:

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

Açılır menü seçeneklerini değere göre seçebilirsiniz: $('#locregion').$('[value="1"]').click();


0

Seçenek değerine veya dizine göre nasıl yapılacağı burada . Bu örnek biraz kaba ama istediğinizi nasıl yapacağınızı gösteriyor:

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

Bunun için özel bir DropDown sınıfı oluşturabilir ve aşağıdaki gibi bir yöntem ekleyebiliriz:

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

Ayrıca, şu anda hangi değerin seçildiğini doğrulamak için aşağıdakilere sahip olabiliriz:

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

0

Aşağıdaki örnek en kolay yoldur. Açıölçer Sürümünü test ettim ve geçtim5.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

Tam kod

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

Bu, angular'ın listeden seçim yapmaya ve indekslemeye yardımcı olabilecek özel konum belirleyiciye sahip olduğu basit tek satırlık bir cevaptır.

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

Bu kod soruyu çözebilirken, sorunun nasıl ve neden çözüldüğüne dair bir açıklama da dahil olmak üzere , gönderinizin kalitesini artırmaya gerçekten yardımcı olur ve muhtemelen daha fazla oy almanıza neden olur. Sadece şu anda soran kişi için değil, gelecekte okuyucular için soruyu yanıtladığınızı unutmayın. Açıklamalar eklemek ve hangi sınırlamaların ve varsayımların geçerli olduğuna dair bir gösterge vermek için lütfen yanıtınızı düzenleyin . Yorumdan
double-beep

-1

CSS özelliğine göre seçeneği seçin

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

veya

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

Locregion (id), organization.parent_id (model adı), seçilen öğenin özellikleridir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.