2

I am mostly familiar with java selenium, and I am new to both JS and Protractor. Lets say I am trying to click an option from a list of options with a common identifier..

var options = $('.options');

How could I get all elements with that common identifier, and then select one by its text? I can not do driver.findElements like I could in java since there is no reference to driver..

This is what I have tried so far but its not working and I think its due to my inexperience with JS

this.selectCompanyCode = function(companyCode) {
    dropDownMenus[0].click();
    var companyCodeOptions = $('[ng-bind-html="companyCode"]');
    companyCodeOptions.filter(function (elem) {
        return elem.getText().then(function text() {
            return text === companyCode;
        });
    }).first().click();
};
Tree55Topz
  • 1,102
  • 4
  • 20
  • 51
  • Did you see my answer? You edited your question after I posted my answer. I added a `.click()` to my answer just now so my code should do the exact same as your code above, except it does not use `.each()` to iterate through the entire array as that's not necessary. If not, add a comment what's not working... trying to help you. – Gunderson Nov 02 '16 at 12:01
  • @Gunderson, I did see your answer. Just didnt want to squeeze that code segment into the comment section. I have updated my code on my post to what I have changed it to from your suggestion, however I am now getting a "cannot read property 'click' of undefined" error.. Could it be how I am trying to pass the companyCode parameter? – Tree55Topz Nov 02 '16 at 13:55
  • Pretty sure that error has to do with `dropDownMenus[0].click()`; Usually you would use `.get()` to retrieve an element by index from an ElementArrayFinder (see the link in my answer below). But also you don't have a reference to dropDownMenus in this function. Is it a global variable? If not, it's definitely undefined. You may also need a return statement from companyCodeOptions.filter. So `return companyCodeOptions.filter(...)` – Gunderson Nov 02 '16 at 15:00

2 Answers2

3

Select all elements with common identifier: $$('.options'); That selects all elements with a class of .options -- equivalent of element.all(by.css('.options')). This returns an ElementArrayFinder. Also see .get() for how to choose an element by index from the ElementArrayFinder.

Find by text, you could use cssContainingText(css, text). For example, var loginBtn = element(by.cssContainingText('button.ng-scope', 'Login'));

But if for some reason those are not providing the expected results, you can use .filter() (docs here) on an ElementArrayFinder to go through the array of elements and find an element based on a condition you specify. For example,

var allOptions = $$('.options');
allOptions.filter(function (elem) {
    return elem.getText().then(function (text) {
        return text === 'What you want';
    });
}).first().click();

And, although I've never used regular Java Selenium (so I don't know if this is the same), but there is indeed a browser reference (and therefore findElements function): http://www.protractortest.org/#/api?view=ProtractorBrowser.

Hope it helps!

Edit:

Using your code:

this.selectCompanyCode = function(companyCode) {
    // where is dropDownMenus defined?  This has function no reference to it.
    dropDownMenus.get(0).click(); // should be this
    var companyCodeOptions = $$('[ng-bind-html="' + companyCode + '"]');
    return companyCodeOptions.filter(function (elem) {
        return elem.getText().then(function text() {
            return text === companyCode;
        });
    }).first().click();
};

second edit: Assuming company code is unique, you probably don't need to use filter. Try this:

this.selectCompanyCode = function(companyCode) {
    dropDownMenus.get(0).click();
    var companyCodeOptions = $('[ng-bind-html="' + companyCode + '"]');
    return companyCodeOptions.click();
};
Gunderson
  • 3,263
  • 2
  • 16
  • 34
  • the dropDownMenus is a locator I identified, var dropDownMenus = $$('.select2-choice.ui-select-match.ng-scope'); I see I was missing a return statement, let me give it a whirl. Thanks for the help! – Tree55Topz Nov 02 '16 at 15:19
  • it is saying companyCodeOptions.filter is not a function – Tree55Topz Nov 02 '16 at 15:23
  • @Tree55Topz sorry my bad, didn't see companyCodeOptions was defined as a single element, I changed it to use `$$` so it creates an array of elements. Also see my second edit, not sure it's even necessary to use `filter()` in this case. – Gunderson Nov 02 '16 at 17:23
  • companyCode is actually the identifier that they all share. But the actual text in the dropdown is what Im trying to pass in to click. So for instance, there are 3 options. All share that identifier, ng-bind-html=companyCode. If I were to do a .getText on ng-bind-html=companyCode[0], it would be different from the text I would get from [1]. that actual .getText value is what I am trying to use to select it. So in the html its like
    Buddys Pizza
    .... Buddys Pizza is what I would pass in because that is the text of the option I want
    – Tree55Topz Nov 02 '16 at 17:33
  • sorry for the confusion haha >. – Tree55Topz Nov 02 '16 at 17:33
  • Oh, then can you just use cssContainingText? `var companyCodeOptions = element(by.cssContainingText('div', 'Buddys Pizza'));` – Gunderson Nov 02 '16 at 17:39
  • Havent tried it that way yet, but I will try. I really wanted to do it the other way though because I think its better practice and it would help me to better understand JS – Tree55Topz Nov 02 '16 at 18:28
1

Use cssContainingText

element(by.cssContainingText(".option", "text")).click();

http://www.protractortest.org/#/api?view=ProtractorBy.prototype.cssContainingText

mvndaai
  • 3,453
  • 3
  • 30
  • 34