J'essaie de sélectionner une option dans une liste déroulante pour les tests angulaires e2e à l'aide de rapporteur.
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 non valide ou illégale a été spécifiéeInformations sur la construction: version: '2.35.0', révision: 'c916b9d', heure: '2013-08-12 15:42:01' Informations système: os.name : 'Mac OS X', os.Arch: 'x86_64', os.version: '10.9 ', Java.version:' 1.6.0_65 ' Informations sur le pilote: driver.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 peut donc pas être interagi avec Durée de la commande ou délai d'attente: 9 millisecondes Informations de construction: version: '2.35.0', révision: 'c916b9d', heure: '2013-08-12 15:42:01' Informations système: os.name: 'Mac OS X', os.Arch: 'x86_64', os.version: '10.9 ', Java.version:' 1.6.0_65 ' ID de session: bdeb8088-d8ad-0f49-aad9-82201c45c63f Informations sur le pilote: 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 = true , webStorageEnabled = true, applicationCacheEnabled = false, takesScreenshot = true}]
Est-ce que n'importe qui peut m'aider s'il vous plaît avec ce problème ou jeter un peu de lumière sur ce que je pourrais faire mal ici.
J'ai eu un problème similaire et j'ai finalement écrit une fonction d'assistance qui sélectionne les valeurs de liste déroulante.
J’ai finalement décidé que j’allais bien à la sélection par numéro d’option et j’ai donc écrit une méthode qui prend un élément et l’optionNumber, et sélectionne cette optionNumber. Si l'optionNumber est null, elle ne sélectionne rien (en laissant le menu déroulant non sélectionné).
var selectDropdownbyNum = function ( element, optionNum ) {
if (optionNum){
var options = element.all(by.tagName('option'))
.then(function(options){
options[optionNum].click();
});
}
};
J'ai écrit un article de blog si vous voulez plus de détails, il couvre également la vérification du texte de l'option sélectionnée dans un menu déroulant: http://technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation/
Pour moi a travaillé comme un charme
element(by.cssContainingText('option', 'BeaverBox Testing')).click();
J'espère que ça aide.
Une approche élégante impliquerait faire une abstraction similaire à ce que les autres liaisons de langage Selenium proposent immédiatement (par exemple, une classe Select
en Python ou Java).
Faisons un wrapper commode} et cachons les détails de l'implémentation à 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 provenant du sujet suivant: Sélectionnez -> option abstraction .
FYI, créé une demande de fonctionnalité: Sélectionnez -> option abstraction .
element(by.model('parent_id')).sendKeys('BKN01');
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();
C'est comme ça que j'ai fait ma sélection.
function switchType(typeName) {
$('.dropdown').element(By.cssContainingText('option', typeName)).click();
};
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();
Essayez ceci, cela fonctionne pour moi:
element(by.model('formModel.client'))
.all(by.tagName('option'))
.get(120)
.click();
Vous pouvez essayer cet espoir que cela fonctionnera
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
});
Une autre façon de définir un élément d'option:
var select = element(by.model('organization.parent_id'));
select.$('[value="1"]').click();
Nous avons écrit une bibliothèque qui comprend 3 façons de sélectionner 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>
La fonction supplémentaire de ces fonctions est qu’ils attendent que l’élément soit affiché avant d’effectuer toute action sur la variable select
.
Vous pouvez le trouver dans npm @ hetznercloud/protractor-test-helper . Des typages pour TypeScript sont également fournis.
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();
Le problème est que les solutions qui fonctionnent sur les boîtes de sélection angulaires normales ne fonctionnent pas avec Angular Material md-select et md-option en utilisant un rapporteur. Celui-ci a été posté par un autre, mais cela a fonctionné pour moi et je suis incapable de commenter son message pour le moment (seulement 23 points de repère). En outre, j'ai nettoyé un peu, au lieu de browser.sleep, j'ai utilisé 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
});
Peut-être pas super élégant, mais efficace:
function selectOption(modelSelector, index) {
for (var i=0; i<index; i++){
element(by.model(modelSelector)).sendKeys("\uE015");
}
}
Ceci envoie simplement la touche vers le bas sur la sélection souhaitée. Dans notre cas, nous utilisons modelSelector mais vous pouvez évidemment utiliser un autre sélecteur.
Puis dans mon modèle d'objet de page:
selectMyOption: function (optionNum) {
selectOption('myOption', optionNum)
}
Et du test:
myPage.selectMyOption(1);
Sélectionnez une option par index:
var selectDropdownElement= element(by.id('select-dropdown'));
selectDropdownElement.all(by.tagName('option'))
.then(function (options) {
options[0].click();
});
Aide pour définir un élément d'option:
selectDropDownByText:function(optionValue) {
element(by.cssContainingText('option', optionValue)).click(); //optionValue: dropDownOption
}
Il y a un problème avec les options de sélection dans Firefox que le piratage de Droogans corrige ce que je veux mentionner ici explicitement, en espérant que cela puisse éviter des ennuis à quelqu'un: https://github.com/angular/protractor/issues/480 .
Même si vos tests réussissent localement avec Firefox, vous constaterez peut-être qu'ils échouent avec CircleCI ou TravisCI, ou avec tout ce que vous utilisez pour le déploiement et le CI. Être conscient de ce problème depuis le début m'aurait fait gagner beaucoup de temps :)
Si ci-dessous est la liste déroulante donnée
<select ng-model="operator">
<option value="name">Addition</option>
<option value="age">Division</option>
</select>
Ensuite, le code protractorjs peut être
var operators=element(by.model('operator'));
operators.$('[value=Addition]').click();
----------
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')
});
J'ai un peu amélioré la solution écrite par PaulL . Tout d'abord, j'ai corrigé le code pour qu'il soit compatible avec la dernière API de 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, afin qu'elle puisse ê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();
});
};
},
Je cherchais des réponses sur la manière de sélectionner une option dans un menu déroulant de modèle et j'ai utilisé cette combinaison qui m'a aidé avec du matériel angulaire.
element (by.model ("ModelName")). click (). element (By.xpath ("emplacement xpath")). click ();
il semble que, lorsque le code est jeté sur une seule ligne, il peut trouver l'élément dans la liste déroulante.
J'ai pris beaucoup de temps pour cette solution. J'espère que cela aidera quelqu'un.
Voici comment procéder par valeur d’option ou par 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
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');
Vous pouvez sélectionner les options du menu déroulant par valeur: $('#locregion').$('[value="1"]').click();
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();
}
}
}
})
}
Nous voulions utiliser la solution élégante en utilisant le matériel angularjs mais cela n’a pas fonctionné car il n’existait aucune balise option/md-option dans le DOM tant que l’on n’avait pas cliqué sur md-select. Donc, la manière "élégante" n'a pas fonctionné pour nous (notez le matériau angulaire!) Voici ce que nous avons fait pour elle à la place, je ne sais pas si c'est la meilleure façon, mais ça marche définitivement 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 de 4 sélections sélectionnées et lorsque la sélection est ouverte, une superposition permet de sélectionner la sélection suivante. C’est la raison pour laquelle nous devons attendre 500 ms pour ne pas avoir de problèmes avec les effets matériels toujours en action.