0

I read a post on SOF here and tried to follow it in my own problem solving but I made myself more problem than a solution.

I tried to findElements, targeting an array of

<img id="4444" class="someclass" src="/images/animg.png" onclick="doSomething(this)" title="contact person Name"/>

from a website, and I'd like to further click on each in a loop and perform operations per each.

As all img tag has attribute "src=/images/animg.png", I wrote:

drv.wait(until.elementLocated(By.xpath(".//*[@src='/images/animg.png']")), 10000, 'img not appeared');
drv.findElements(By.xpath(".//*[@src='/images/animg.png']")).then(function (imgs) {
    let myimgs = imgs.map(function (elem) {
        elem.getAttribute("src").then(function (x) {
            return elem; //or try elem.getAttribute("src");
        });
    });
    thepromise.all(myimgs).then(function (allit) {
        console.log('y: ' + allit[0]);
    });

});

The confusion:
1. if I issue "return elem", to further do "elem.click()", I get a promise object (using util.inspect easily seen)
2. I made a conclusion, that this elem, is a promise object
3. if I issue "return elem.getAttribute("src");" I have the src returned, that makes me think that elem is NOT a promise, but the
4. unfortunately, trying to issue "allit[0].click()" which is "elem.click()" fails as it shows a promise object!

So I am confused what is really happening there. Could you please explain? (I googled half a day and still can not understand anywhere).

Buaban
  • 5,029
  • 1
  • 17
  • 33
Ariam1
  • 1,673
  • 2
  • 13
  • 32

1 Answers1

1

The problem is that you forgot to return value of the map at line:

let myimgs = imgs.map(function (elem) {
    elem.getAttribute("src").then(function (x) {
    ...

See my examples below.

driver.get("http://buaban.com");
driver.wait(until.elementLocated(By.xpath(".//*[contains(@src,'.png')]")), 10000, 'img not appeared');

driver.findElements(By.xpath(".//*[contains(@src,'.png')]")).then(function (imgs) {
    // Example 1 - return string
    let allImgSrcs = imgs.map(function (elem) {
        return elem.getAttribute("src").then((src)=>{
            return "test 1 - " + src;
        });
    });

    Promise.all(allImgSrcs).then(function (imgSrcs) {
        imgSrcs.forEach((imgSrc)=>{ 
            console.log(imgSrc);
        });
    });

    // Example 2 - return string
    let allImgSrcs2 = imgs.map(function (elem) {
        return elem.getAttribute("src").then((src)=>{
            return elem.getAttribute("src").then(()=>{
                return "test 2 - " + src;
            });
        });
    });

    Promise.all(allImgSrcs2).then(function (imgSrcs) {
        imgSrcs.forEach((imgSrc)=>{ 
            console.log(imgSrc);
        });
    });

    // Example 3 - filter and then return WebElement
    let allSeleniumElements = imgs.map(function (elem) {
        return elem.getAttribute("src").then((src)=>{
            if(src.indexOf("selenium")>0) {
                return elem;
            }
        });
    });

    Promise.all(allSeleniumElements).then(function (imgEls) {
        imgEls.forEach((ele)=>{ 
            if(typeof ele !=="undefined") {
                //console.log(ele);
                ele.getAttribute("src").then((src)=>{
                    console.log("Test 3 - " + src);
                });
            }
        });
    });

    // Example 4 - Click WebElement
    imgs.forEach((ele)=>{ 
        ele.click();
    });

});

The console will be:

test 1 - http://www.buaban.com/wp-content/uploads/2017/08/Logo-sublime-3.png
test 1 - http://www.buaban.com/wp-content/uploads/2016/07/selenium-logo-featured.png
test 1 - http://www.buaban.com/wp-content/uploads/2016/07/selenium-logo-featured.png
test 1 - http://www.buaban.com/wp-content/uploads/2017/04/msdn_new_logo-edit.png
test 1 - http://www.buaban.com/wp-content/uploads/2016/07/apachejmeter-crop.png
test 1 - http://www.buaban.com/wp-content/uploads/2016/07/apachejmeter-crop.png
test 2 - http://www.buaban.com/wp-content/uploads/2017/08/Logo-sublime-3.png
test 2 - http://www.buaban.com/wp-content/uploads/2016/07/selenium-logo-featured.png
test 2 - http://www.buaban.com/wp-content/uploads/2016/07/selenium-logo-featured.png
test 2 - http://www.buaban.com/wp-content/uploads/2017/04/msdn_new_logo-edit.png
test 2 - http://www.buaban.com/wp-content/uploads/2016/07/apachejmeter-crop.png
test 2 - http://www.buaban.com/wp-content/uploads/2016/07/apachejmeter-crop.png
Test 3 - http://www.buaban.com/wp-content/uploads/2016/07/selenium-logo-featured.png
Test 3 - http://www.buaban.com/wp-content/uploads/2016/07/selenium-logo-featured.png
Buaban
  • 5,029
  • 1
  • 17
  • 33
  • It's now clear about returning attribute. Thank you very much, I'm so sorry I couldn't clearly explain my intention. In fact my final goal is to return img as element and then click on them in a loop, perhaps a generator-yield. Could you kindly tell me, how I could do something like "return elem.then()" to finally issue "elem.click()" please? As I explained above, this img has an attribute "onclick=doSomething(this)" and my final reason is to force it to run and it's 2 days I can't have it! – Ariam1 Aug 12 '17 at 12:39
  • @AdrianDain I have added the example #4. Is that what you want? – Buaban Aug 12 '17 at 12:48
  • maybe for elem.click() I even do not need to use promises and do it right after findElements is correct? – Ariam1 Aug 12 '17 at 13:13