0

I have challenges accessing a value from a dropdown list. The List is created using Bootstrap's dropdown.js.

I created a custom command in "Nightwatch" with 2 input parameters: "locator" of the dropdown button and the value to be found on the list. The output should be selected value from the dropdown.

Problem: Dropdown gets open but attempts to access values from it generates the error:

TypeError: this.elementIdAttribute is not a function

I've read through all the posts on stack overflow and based on them the syntax is correct. I'm out of ideas.

Under comments is the path to the dropdown element and change the value of li:nth-child(2) I can select every element on the list.

Below is the code (wrapped in *** is the place that produce the error):

exports.command = function(locator, valueToClick) {
    var dropdown;
    //locator sample
    //.click('#form > div.panel.panel-primary > div.panel-body > div:nth-child(1) > div > div.btn-group.bootstrap-select.form-control.parsley-validated > button')
    //.click('#form > div.panel.panel-primary > div.panel-body > div:nth-child(1) > div > div.btn-group.bootstrap-select.form-control.parsley-validated.open > div > ul > li:nth-child(2) > a > span.text')
    // cut " > button" from the end
    var dropdownElementLocator = locator.slice(0,locator.length-9);
    //var openDrop = '#form > div.panel.panel-primary > div.panel-body > div:nth-child(1) > div > div.btn-group.bootstrap-select.form-control.parsley-validated.open > div > ul li a span.text'
    var openDrop = dropdownElementLocator + '.open > div > ul > li'

    this
        .click(locator)
        .elements('css selector', openDrop, function(result){
           console.log("number of elements = " + result.value.length);
           console.log(result);
           result.value.forEach(function (element){
                console.log(***this.elementIdAttribute***(element.ELEMENT, 'a').value);
           });

           var position = -1;
           var i = 0;
           result.value.forEach(function(value){
            i++;
            var loc = openDrop + ':nth-child(' + i + ') > a > span.text'
           })

           position = position>-1 ? position : 0;
           console.log("final position " + i )
           //add ".open > div > ul > li:nth-child(2) > a > span.text"
           dropdownElementLocator = dropdownElementLocator + ".open > div > ul > li:nth-child(" + (position+1) + ") > a > span.text";
           this.click(dropdownElementLocator);
        })      
};
Colin Cline
  • 1,291
  • 1
  • 12
  • 25
Ivana
  • 85
  • 6

2 Answers2

1

The error was removed by preserving the value of this. Since the value of this changes throughout the code.

exports.command = function(locator, valueToClick) {
    var dropdown;
    var openDrop = dropdownElementLocator + '.open > div > ul > li'

    // preserve the value of this since its scope changes trhoughout the code
    browser = this;
    browser
        .click(locator)
        .elements('css selector', openDrop, function(result){
           console.log("number of elements = " + result.value.length);
           console.log(result);
           result.value.forEach(function (element){
                console.log(browser.elementIdAttribute(element.ELEMENT, 'a').value);
           }); 

           var position = -1;
           var i = 0;
           result.value.forEach(function(value){
            i++;
            var loc = openDrop + ':nth-child(' + i + ') > a > span.text'
            //this.element('css selector', loc, function(res) {
            //       console.log('value ' + i + ': ' + res)
            //})
           })

           position = position>-1 ? position : 0;
           console.log("final position " + i )
           //add ".open > div > ul > li:nth-child(2) > a > span.text"
           dropdownElementLocator = dropdownElementLocator + ".open > div > ul > li:nth-child(" + (position+1) + ") > a > span.text";
           browser.click(dropdownElementLocator);
        })      
};

Problem: I'm still not able to access the values from the dropdown

Ivana
  • 85
  • 6
  • Just a quick note, you can pass `this` into your `forEach()` instead of assigning it to a variable. It works if you do it like this `array.forEach(() => {}, this)`. Then you will be able to use `this.elementIdAttribute` inside the loop the way you want. See this example https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Using_thisArg – tehbeardedone Jan 04 '18 at 14:10
  • @Ivana, i am running into the same problem. I am trying to select a value from drop down but not able to do that. The drop down has `ul li ` tag. I used similar to your command but when i add the selector using `@dropDownTransValue` sign in page object using the customized command , its not parsing the selector. It is parsing the selector name. – James Jan 27 '20 at 00:57
0

Resolved using this post

exports.command = function(locator, valueToClick) {
    var dropdown, position;
    //locator sample
    //.click('#form > div.panel.panel-primary > div.panel-body > div:nth-child(1) > div > div.btn-group.bootstrap-select.form-control.parsley-validated > button')
    //.click('#form > div.panel.panel-primary > div.panel-body > div:nth-child(1) > div > div.btn-group.bootstrap-select.form-control.parsley-validated.open > div > ul > li:nth-child(2) > a > span.text')
    // cut " > button" from the end
    var dropdownElementLocator = locator.slice(0,locator.length-9);
    //var openDrop = '#form > div.panel.panel-primary > div.panel-body > div:nth-child(1) > div > div.btn-group.bootstrap-select.form-control.parsley-validated.open > div > ul li a span.text'
    var openDrop = dropdownElementLocator + '.open > div > ul > li'

    // preserve the value of this since its scope changes trhoughout the code
    browser = this;
    browser
        .click(locator)
        .elements('css selector', openDrop, function(result){
            var i = 0;
            result.value.forEach(function (jsonWebElement){
                var jsonWebElementId = jsonWebElement.ELEMENT;
                browser.elementIdText(jsonWebElementId, function(jsonElement){
                    var text = jsonElement.value;
                    i++;
                    console.log("text " + i + " : " + text + " text.indexOf(valueToClick) - " + text.indexOf(valueToClick));

                    if(text.indexOf(valueToClick) == 0){
                        position = i;
                        console.log("position inside loop: " + position);
                    }
                });
            });
        })
        .perform(function(){
            position = position>-1 ? position : 1;
            console.log("final position " + position )
            //add ".open > div > ul > li:nth-child(2) > a > span.text"
            dropdownElementLocator = dropdownElementLocator + ".open > div > ul > li:nth-child(" + position + ") > a > span.text";
            browser.click(dropdownElementLocator);
        })         
};
Ivana
  • 85
  • 6