Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selenium webdriver iterate and navigate over multiple links in node.js

Migrating away from Casper.js to Selenium to have more tools.

Attempting to iterate through multiple links and navigate them using node.js and selenium-webdriver.

Can't find any documentation or examples and I keep getting an error no matter which loop I try to run.

iLinkCount = oLinks.length;
    console.log( oLinks );
    console.log( iLinkCount );

Code above outputs the link count to the console but I am unable to get their href tags to continue on with my testing.

driver.findElements(webdriver.By.css( 'snip' ) ).then(function( oLinks ) {
// driver.findElements(webdriver.By.xpath( "//snip" ) ).then(function( oLinks ) {
    iLinkCount = oLinks.length;
    console.log( oLinks );
    console.log( iLinkCount );

    // for( var oLink in oLinks ){
    //     var sLink = oLink.getAttribute('href');
    //     console.log( sLink );
    // }


    for( var i = 0; i < iLinkCount; i++ ){
        var oLink = oLinks.get( i );
        console.log( oLink );
        // var sLink = oLinks[ i ].getAttribute('href');
        // console.log( sLink );
    }
});

Every loop I attempt to use to iterate over the links I get an error:

TypeError: undefined is not a function

What's wrong with my loops?

Any good references on examples/REAL USAGE documentation on driving selenium-webdriver with node?

After searching far and wide all that appears to be semi-documented are java/python samples.

like image 510
Vladimir Ramik Avatar asked Jul 06 '15 00:07

Vladimir Ramik


1 Answers

I would say that this documentation is quite good.

The problem with your code is, when you look at the documentation, findElements returns an array of WebElement, and that has no get method, one thing I have learnt is, if you are going to play with selenium in javascript, you need to understands the concept of Promise properly( and make sure do not do any anti-promise pattern), simply put, most of the cases you talk to the driver( call some method in it), you get a promise in return that has the value you desire and not the actual value itself.

The function for retriving href based on css selector:

function getAllHrefs(driver, cssValue){
    var selector;
    if(!cssValue)   selector = By.tagName('a');
    else            selector = By.css(cssValue);
    return driver.findElements(selector).then(function(oLinks){
        var allPromises = oLinks.map(function(oLink){
            return oLink.getAttribute('href');
        });
        return Driver.promise.all(allPromises);
    });     
}

Example for the above function:

var dummyPage = 'http://google.com'
 , Driver = require('selenium-webdriver')
 , By = require('selenium-webdriver').By
 , chrome = require('selenium-webdriver/chrome')
 , driver
;


driver = getDriverInstance();
driver.get(dummyPage);
getAllHrefs(driver).then(function(hrefs){
    console.log('got hrefs: ', hrefs.length, hrefs);
});


function getAllHrefs(driver, cssValue){
    var selector;
    if(!cssValue)   selector = By.tagName('a');
    else            selector = By.css(cssValue);
    return driver.findElements(selector).then(function(oLinks){
        var allPromises = oLinks.map(function(oLink){
            return oLink.getAttribute('href');
        });
        return Driver.promise.all(allPromises);
    });     
}

function getDriverInstance(){  
    var driverInstance = new Driver.Builder()
        .usingServer()
        .withCapabilities({
            browserName: 'chrome'
        })
        .setChromeOptions(
            new chrome.Options()
                .addArguments('--privileged')
                .addArguments('--no-sandbox')
        )
        .build();
    return driverInstance;
}
like image 101
mido Avatar answered Oct 06 '22 04:10

mido