So wählen Sie eine Option in Dropdown-Winkelmesser-E2E-Tests aus


121

Ich versuche, eine Option aus einem Dropdown für die Winkel-e2e-Tests mit einem Winkelmesser auszuwählen.

Hier ist das Code-Snippet der Auswahloption:

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

Ich habe versucht:

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

Dies gibt mir den folgenden Fehler:

Es wurde eine ungültige oder unzulässige Zeichenfolge angegeben. Build-Info: Version: '2.35.0', Revision: 'c916b9d', Zeit: '2013-08-12 15:42:01' Systeminfo: os.name: 'Mac OS X' , os.arch: 'x86_64', os.version: '10 .9 ', java.version:' 1.6.0_65 'Treiberinfo: driver.version: unbekannt

Ich habe auch versucht:

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

Dies gibt mir den folgenden Fehler:

ElementNotVisibleError: Das Element ist derzeit nicht sichtbar und kann daher möglicherweise nicht mit der Befehlsdauer oder dem Zeitlimit interagiert werden: 9 Millisekunden Build-Info: Version: '2.35.0', Revision: 'c916b9d', Zeit: '2013-08-12 15:42: 01 'Systeminfo: os.name:' Mac OS X ', os.arch:' x86_64 ', os.version: '10 .9', java.version: '1.6.0_65' Sitzungs-ID: bdeb8088-d8ad-0f49-aad9 -82201c45c63f Treiberinformationen: org.openqa.selenium.firefox.FirefoxDriver Funktionen [{platform = MAC, acceptSslCerts = true, javascriptEnabled = true, browserName = Firefox, rotatable = false, locationContextEnabled = true, version = 24.0, cssSelectorsEnabled = = true, handleAlerts = true, browserConnectionEnabled = true, nativeEvents = false, webStorageEnabled = true, applicationCacheEnabled = false, takeScreenshot = true}]

Kann mir bitte jemand bei diesem Problem helfen oder etwas Licht auf das werfen, was ich hier falsch machen könnte?

Antworten:


88

Ich hatte ein ähnliches Problem und schrieb schließlich eine Hilfsfunktion, die Dropdown-Werte auswählt.

Ich entschied schließlich, dass ich gut nach Optionsnummer auswählen konnte, und schrieb daher eine Methode, die ein Element und die optionNumber verwendet und diese optionNumber auswählt. Wenn die optionNumber null ist, wird nichts ausgewählt (die Dropdown-Liste bleibt nicht ausgewählt).

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

Ich habe einen Blog-Beitrag geschrieben, wenn Sie mehr Details wünschen. Er behandelt auch die Überprüfung des Textes der ausgewählten Option in einer Dropdown-Liste: http://technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation/


1
Hat bei mir nicht funktioniert, habe element.findElements ist keine Funktion.
Justin

251

Für mich hat wie ein Zauber gearbeitet

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

Ich hoffe es hilft.


2
Kleinere Anmerkung - nur v0.22 (ich habe gerade meinen Code durch diesen ersetzt und musste ein Upgrade durchführen, um ihn zu erhalten)
PaulL

Gibt es eine Möglichkeit, Elemente damit auszurichten? Zum Beispiel mit doppelten Statusauswahlmenüs.
Christopher Marshall

11
Christopher ElementFinderist element(by.css('.specific-select')).element(by.cssContainingText('option', 'BeaverBox Testing')).click();
kettenfähig

6
Beachten Sie, dass Sie teilweise Übereinstimmungen erhalten können, sodass "Klein" mit "Extra Klein" übereinstimmt.
TrueWill

3
So fügen Sie den Kommentar von TrueWill hinzu: Der Nachteil dieser Lösung besteht darin, dass bei zwei ähnlichen Optionen die zuletzt gefundene Option verwendet wird, die aufgrund der falschen Auswahl Fehler verursacht hat. Was für mich funktioniert hat war stackoverflow.com/a/25333326/1945990
Mike W

29

Ein eleganter Ansatz würde darin bestehen , eine Abstraktion zu erstellen, die der von anderen Selen-Sprachbindungen ähnelt (z. B. SelectKlasse in Python oder Java).

Lassen Sie uns einen praktischen Wrapper erstellen und Implementierungsdetails darin verbergen:

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;

Anwendungsbeispiel (beachten Sie, wie lesbar und benutzerfreundlich es ist):

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

Lösung aus folgendem Thema: Wählen Sie -> Optionsabstraktion .


Zu Ihrer Information, eine Feature-Anfrage erstellt: Wählen Sie -> Optionsabstraktion .


Warum verwenden Sie 'return' in den ausgewählten Funktionen? Ist das notwendig
Michiel

1
@ Michael guter Punkt. Möglicherweise erforderlich, wenn Sie das von zurückgegebene Versprechen explizit auflösen möchten click(). Vielen Dank.
Alecxe

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

1
Es ist das Richtigste für mich. Mit cssContainingText stellen Sie nicht sicher, dass Sie das gewünschte Feld erfassen. Stellen Sie sich vor, Sie haben 2 Auswahlfelder mit denselben Werten. +1
YoBre

4
Entschuldigung, was ist BKN01?
Gerfried

1
@Gerfried BKN01 ist der Text, den Sie aus der Dropdown-Liste auswählen möchten.
MilanYadav

@ GalBracha Sorry hat dich nicht
erwischt

Wenn Sie eine andere Option haben, die denselben Prefex wie BKN01 verwendet, funktioniert dies nicht. Ein zufälliger wird abgeholt.
zs2020

15

Um auf eine bestimmte Option zuzugreifen, müssen Sie den Selektor nth-child () angeben:

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

Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag.
JPW

@jpw ist meine Antwort falsch. oder ist es einfach die Formulierung meiner Antwort, die falsch ist?
bekite

Die Formulierung einer Antwort als Frage ist warum. Ich weiß nicht, ob es die richtige Antwort ist. Wenn ja, sollten Sie es als solches formulieren.
JPW

3
@bekite Hat bei mir nicht funktioniert. Immer noch den Fehler erhalten Element Nicht sichtbarer Fehler, als ich Ihren Vorschlag versuchte
Ranjan Bhambroo

8

So habe ich meine Auswahl getroffen.

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

5

So habe ich es gemacht:

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

Verwenden Sie die Winkelmessermethode, um zu warten, bis der Winkel die ausstehende Verarbeitung abgeschlossen hat waitForAngular().
Avi Cherry

5

Versuchen Sie dies, es funktioniert für mich:

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

4

Sie können diese Hoffnung versuchen, es wird funktionieren

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

Eine andere Möglichkeit, ein Optionselement festzulegen:

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

var orderTest = element (by.model ('ctrl.supplier.orderTest')) orderTest. $ ('[value = "1"]'). click ();
Ich erhalte

3

So wählen Sie Elemente (Optionen) mit eindeutigen IDs wie hier aus:

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

Ich benutze dies:

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

3

Wir haben eine Bibliothek geschrieben, die drei Möglichkeiten zur Auswahl einer Option enthält:

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>

Ein zusätzliches Merkmal dieser Funktionen ist, dass sie darauf warten, dass das Element angezeigt wird, bevor eine Aktion auf dem ausgeführt selectwird.

Sie finden es auf npm @ hetznercloud / Winkelmesser-Test-Helfer . Es werden auch Typisierungen für TypeScript bereitgestellt.


2

Vielleicht nicht super elegant, aber effizient:

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

Dies sendet nur den Schlüssel auf die gewünschte Auswahl. In unserem Fall verwenden wir modelSelector, aber Sie können natürlich jeden anderen Selektor verwenden.

Dann in meinem Seitenobjektmodell:

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

Und aus dem Test:

myPage.selectMyOption(1);

2

Das Problem ist, dass Lösungen, die mit regulären Winkelauswahlfeldern funktionieren, nicht mit Winkelmesser md-select und md-option unter Verwendung eines Winkelmessers funktionieren. Dieser wurde von einem anderen gepostet, aber er hat bei mir funktioniert und ich kann seinen Beitrag noch nicht kommentieren (nur 23 Wiederholungspunkte). Außerdem habe ich es ein wenig aufgeräumt, anstatt browser.sleep, habe ich browser.waitForAngular () verwendet;

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

Ich benutze nur diese:element(by.model('selectModel')).click(); element(by.css('md-option[value="searchOptionValue"]')).click();
Luan Nguyen

Hier ist ein anderer Ansatz: mdSelectElement.getAttribute('aria-owns').then( function(val) { let selectMenuContainer = element(by.id(val)); selectMenuContainer.element(by.css('md-option[value="foo"]')).click(); } );
Gbruins

1

Es gibt ein Problem bei der Auswahl von Optionen in Firefox, das Droogans 'Hack- Korrekturen behoben haben , die ich hier explizit erwähnen möchte, in der Hoffnung, dass dadurch jemandem Probleme erspart werden : https://github.com/angular/protractor/issues/480 .

Selbst wenn Ihre Tests lokal mit Firefox bestanden werden, stellen Sie möglicherweise fest, dass sie unter CircleCI oder TravisCI oder was auch immer Sie für CI und Bereitstellung verwenden, fehlschlagen. Von Anfang an über dieses Problem informiert zu sein, hätte mir viel Zeit gespart :)


1

Hilfsprogramm zum Festlegen eines Optionselements:

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

1

Wenn unten das angegebene Dropdown-

            <select ng-model="operator">
            <option value="name">Addition</option>
            <option value="age">Division</option>
            </select>

Dann kann der Winkelmesser-Code

        var operators=element(by.model('operator'));
    		operators.$('[value=Addition]').click();

Quelle: https://github.com/angular/protractor/issues/600


1

Option nach Index auswählen:

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

1

Ich habe die von PaulL geschriebene Lösung etwas verbessert. Zuerst habe ich den Code so korrigiert, dass er mit der letzten Winkelmesser-API kompatibel ist. Und dann deklariere ich die Funktion im Abschnitt 'onPrepare' einer Protractor-Konfigurationsdatei als Mitglied der Browserinstanz , damit auf sie von jeder e2e-Spezifikation verwiesen werden kann.

  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

Ich habe im Internet nach einer Antwort gesucht, wie eine Option in einem Modell-Dropdown-Menü ausgewählt werden kann, und ich habe diese Kombination verwendet, die mir bei Angular-Material geholfen hat.

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

Es scheint, dass beim Werfen des Codes in einer Zeile das Element in der Dropdown-Liste gefunden werden kann.

Ich habe viel Zeit für diese Lösung gebraucht. Ich hoffe, dass dies jemandem hilft.


0

Wir wollten die elegante Lösung dort oben mit AngularJS-Material verwenden, aber es hat nicht funktioniert, da es im DOM tatsächlich keine Option / MD-Option-Tags gibt, bis auf die MD-Auswahl geklickt wurde. Der "elegante" Weg hat also bei uns nicht funktioniert (beachten Sie das eckige Material!). Hier ist, was wir stattdessen dafür getan haben. Ich weiß nicht, ob es der beste Weg ist, aber es funktioniert jetzt definitiv

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

Wir mussten 4 Auswahlen auswählen, und während die Auswahl geöffnet ist, gibt es eine Überlagerung bei der Auswahl der nächsten Auswahl. Deshalb müssen wir 500 ms warten, um sicherzustellen, dass wir keine Probleme mit den Materialeffekten bekommen, die noch in Aktion sind.


0

Eine andere Möglichkeit, ein Optionselement festzulegen:

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

Sie können Dropdown-Optionen nach Wert auswählen: $('#locregion').$('[value="1"]').click();


0

Hier erfahren Sie, wie Sie dies entweder nach Optionswert oder nach Index tun . Dieses Beispiel ist etwas grob, zeigt aber, wie Sie das tun, was Sie wollen:

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

Wir können hierfür eine benutzerdefinierte DropDown-Klasse erstellen und eine Methode hinzufügen als:

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

Um zu überprüfen, welcher Wert aktuell ausgewählt ist, können wir außerdem Folgendes haben:

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

0

Das folgende Beispiel ist der einfachste Weg. Ich habe die Winkelmesser-Version getestet und bestanden5.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

Vollständiger Code

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

Dies ist eine einfache einzeilige Antwort, bei der Angular über einen speziellen Locator verfügt, mit dessen Hilfe Sie aus der Liste auswählen und indizieren können.

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

Während dieser Code die Frage lösen kann, einschließlich einer Erklärung, wie und warum dies das Problem löst, würde dies wirklich dazu beitragen, die Qualität Ihres Beitrags zu verbessern, und wahrscheinlich zu mehr Up-Votes führen. Denken Sie daran, dass Sie in Zukunft die Frage für die Leser beantworten, nicht nur für die Person, die jetzt fragt. Bitte bearbeiten Sie Ihre Antwort, um Erklärungen hinzuzufügen und anzugeben, welche Einschränkungen und Annahmen gelten. Aus der Überprüfung
Doppel-Piepton

-1

Wählen Sie die Option nach CSS-Eigenschaft aus

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

oder

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

Wobei locregion (id), organisation.parent_id (Modellname) die Attribute des ausgewählten Elements sind.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.