Comment sélectionner l'option dans les tests drop down protractorjs e2e

j'essaie de sélectionner une option à partir d'une goutte pour les tests E2E angulaires en utilisant protractor.

Voici l'extrait de code de l'option 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>

j'ai essayé:

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

cela me donne l'erreur suivante:

une chaîne invalide ou illégale a été spécifiée Build info: version: '2.35.0', révision: 'c916b9d', heure: '2013-08-12 15: 42: 01" Informations système: os.nom: "Mac OS X", os.arc: 'x86_64', os.version: '10.9", de java.version: "1.6.0_65" Des informations sur les pilotes: pilote.version: inconnue

j'ai aussi essayé:

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

cela me donne l'erreur suivante:

ElementNotVisibleError: l'Élément n'est pas visible et ne peuvent donc pas être en interaction avec Commande duration ou timeout: 9 millisecondes Construire info: version: '2.35.0', révision: 'c916b9d', heure: '2013-08-12 15: 42: 01' Informations système: os.nom: "Mac OS X", os.arc: 'x86_64', os.version: '10.9", de java.version: "1.6.0_65" Nom de Session: bdeb8088-d8ad-0f49-aad9-82201c45c63f Informations sur le conducteur: org.openqa.nium.Firefox.FirefoxDriver Capacités [{platform=MAC, acceptSslCerts= true, javascriptEnabled = true, browserName = firefox, rotatable=false, locationtextenabled=true, version = 24.0, cssSelectorsEnabled=true, databaseEnabled=true, handlesAlerts=true, browserConnectionEnabled=true, nativeEvents=false, webStorageEnabled=true, applicationCacheEnabled=false, takesScreenshot = true}]

quelqu'un Peut-il m'aider avec ce problème ou de jeter un peu de lumière sur ce que je fais de mal ici.

101
demandé sur alecxe 2013-10-26 01:08:07

27 réponses

j'ai eu un problème similaire, et j'ai finalement écrit une fonction d'aide qui sélectionne les valeurs de descente.

j'ai finalement décidé que j'allais bien choisir par numéro d'option, et j'ai donc écrit une méthode qui prend un élément et l'optionNumber, et sélectionne cet optionNumber. Si optionNumber est nul, il ne sélectionne rien (laissant la liste déroulante non sélectionnée).

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

j'ai écrit un billet de blog si vous voulez plus de détails, il couvre également vérifier le texte de l'option sélectionnée dans une liste déroulante: http://technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation /

73
répondu PaulL 2018-05-11 16:13:37

Pour moi a fonctionné comme un charme

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

J'espère que ça aidera.

233
répondu Fatz 2015-05-16 14:31:46

une approche élégante impliquerait faire une abstraction similaire à ce que d'autres fixations de langage sélénium offrent hors de la boîte (par exemple Select classe en Python ou en Java).

faisons un convenient wrapper et cacher les détails de la mise en œuvre à l'intérieur:

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;

exemple d'utilisation (notez à quel point il est lisible et facile à utiliser):

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

Solution tirée du thème suivant: sélectionner -> option abstraction .


FYI, a créé une requête de caractéristique: sélectionner -> abstraction d'option .

23
répondu alecxe 2017-05-23 11:54:41
element(by.model('parent_id')).sendKeys('BKN01');
20
répondu Sandesh Danwale 2014-10-16 09:29:44

pour accéder à une option spécifique, vous devez fournir le sélecteur nth-child ():

ptor.findElement(protractor.By.css('select option:nth-child(1)')).click();
15
répondu bekite 2013-10-25 22:44:56

C'est comme ça que j'ai fait ma sélection.

function switchType(typeName) {
     $('.dropdown').element(By.cssContainingText('option', typeName)).click();
};
6
répondu Xotabu4 2018-03-02 13:08:30

Voici comment je l'ai fait:

$('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();
5
répondu Droogans 2014-04-29 16:24:45

Essayer, c'est de travailler pour moi:

element(by.model('formModel.client'))
    .all(by.tagName('option'))
    .get(120)
    .click();
5
répondu Javeed 2015-05-16 14:25:33

Vous pouvez essayer ce espère que cela va fonctionner

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
});
3
répondu Zahid Afaque 2015-02-05 14:30:52

une autre façon de définir un élément d'option:

var select = element(by.model('organization.parent_id'));
select.$('[value="1"]').click();
3
répondu surya narayana raju g 2016-10-06 07:24:48

nous avons écrit une bibliothèque qui comprend 3 façons de choisir une option:

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>

caractéristique Supplémentaire de ce qu'ils attendent de l'élément à afficher avant toute action sur le select est effectuée.

Vous pouvez le trouver sur npm @hetznercloud/rapporteur-test-helper . Typings pour les caractères d'imprimerie sont fournis.

3
répondu crashbus 2018-06-11 10:26:48

peut-être pas très élégant, mais efficace:

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

cela envoie juste la clé vers le bas sur le select que vous voulez, dans notre cas, nous utilisons modelSelector mais évidemment vous pouvez utiliser n'importe quel autre selector.

puis dans mon modèle d'objet de page:

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

et du test:

myPage.selectMyOption(1);
2
répondu Calahad 2014-03-27 05:16:02

pour sélectionner des éléments (options) avec des identifiants uniques comme ici:

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

j'utilise ceci:

element(by.css('[value="' + neededBarId+ '"]')).click();
2
répondu Vladius 2015-05-19 13:59:36

le problème est que les solutions qui fonctionnent sur les boîtes régulières de sélection angulaire ne fonctionnent pas avec le matériau angulaire md-select et md-option en utilisant protractor. Celui-ci a été posté par un autre, mais il a fonctionné pour moi et je ne suis pas encore en mesure de commenter sur son poste (seulement 23 points rep). Aussi, j'ai nettoyé un peu, au lieu de navigateur.le sommeil, j'ai utilisé le navigateur.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
});
2
répondu peterhendrick 2015-07-29 01:27:28

il y a un problème avec la sélection d'options dans Firefox que Correction de hack de Droogans que je veux mentionner ici explicitement, en espérant qu'il pourrait sauver quelqu'un certains problème: https://github.com/angular/protractor/issues/480 .

même si vos tests sont réussis localement avec Firefox, vous pourriez trouver qu'ils ne fonctionnent pas sur CircleCI ou TravisCI ou quoi que vous utilisiez pour CI&deployment. En étant conscient de ce problème à partir de la début m'aurait sauvé beaucoup de temps:)

1
répondu Julia Jacobs 2017-05-23 12:34:37

Aide pour définir l'option de l'élément:

selectDropDownByText:function(optionValue) {
            element(by.cssContainingText('option', optionValue)).click(); //optionValue: dropDownOption
        }
1
répondu Adnan Ghaffar 2016-12-30 18:49:55

Si ci-dessous est la baisse indiquée -

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

puis protractorjs code peut être -

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

Source - https://github.com/angular/protractor/issues/600

1
répondu Ajay Patil 2017-02-26 10:19:09

sélectionner L'option par Index:

var selectDropdownElement= element(by.id('select-dropdown'));
selectDropdownElement.all(by.tagName('option'))
      .then(function (options) {
          options[0].click();
      });
1
répondu Shardul 2017-04-17 15:17:28

nous voulions utiliser la solution élégante là-haut en utilisant le matériau angularjs mais cela n'a pas fonctionné car il n'y a en fait aucune option / md-option dans le DOM tant que le md-select n'a pas été cliqué. Ainsi ,la méthode" élégante " n'a pas fonctionné pour nous (notez le matériau angulaire!) Voici ce que nous avons fait pour elle à la place, ne sais pas si c'est la meilleure façon, mais son fonctionnement défini maintenant

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

nous avions besoin d'avoir 4 sélections sélectionnées et pendant que le select est ouvert, il y a une superposition dans la manière de sélectionner le prochain select. c'est pourquoi nous devons attendre 500m pour nous assurer de ne pas avoir de problèmes avec les effets matériels toujours en action.

0
répondu pascalwhoop 2015-05-16 14:28:51

une autre façon de définir un élément d'option:

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
répondu flaviomeira10 2015-05-22 17:18:07
----------
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
répondu Pramod Dutta 2016-05-20 08:55:36

j'ai été à la recherche du filet pour une réponse sur la façon de choisir une option dans un dropdown modèle et j'ai utilisé cette combinaison qui m'a aidé avec le matériel angulaire.

élément(par.modèle("ModelName")).cliquer.)(élément(Par.xpath('emplacement xpath')).cliquez sur();

il semble qu'en lançant le code tout en une seule ligne, il pourrait trouver l'élément dans la liste déroulante.

a pris beaucoup de temps pour cette solution j'espère que ce aide à quelqu'un.

0
répondu user3460150 2016-08-31 11:33:42

vous pouvez sélectionner les options dropdown par valeur: $('#locregion').$('[value="1"]').click();

0
répondu Sander Lepik 2016-11-22 11:34:39

j'ai amélioré un peu la solution écrite par PaulL. Tout d'abord, j'ai corrigé le code pour qu'il soit compatible avec la dernière API Protractor. Et puis je déclare la fonction dans la section 'onPrepare' d'un fichier de configuration de Protractor en tant que membre de l'instance browser , de sorte qu'elle peut être référencée sous n'importe quelle spécification 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();
        });
    };
  },
0
répondu trunikov 2017-05-26 12:12:15

Voici comment le faire par la valeur de l'option ou l'index . Cet exemple est un peu brut, mais il montre comment faire ce que vous voulez:

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
répondu KVarmark 2018-08-27 09:52:14

sélectionner l'option correspondant à la propriété CSS

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

ou

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

Où locregion(id), de l'organisation.parent_id(nom du modèle) sont les attributs de l'élément select.

-1
répondu Kanhaiya Kumar 2017-10-22 08:22:25

vous pouvez sélectionner les options de réduction comme ceci:

element(by.xpath(//*[@id="locregion"]//option[contains(text(),"Ranjans Mobile Testing")]')).click();
-1
répondu user8872303 2017-11-02 05:40:24