tarquin tarquin - 4 years ago 370
Java Question

Unable to locate element (widget) using Selenium NoSuchElementException

I am trying to click on a widget button which has the functionality to expands and collapse it. For some reason I am having some difficulties in locating this element. I always get a NoSuchElementException thrown:

org.openqa.selenium.NoSuchElementException:
no such element: Unable to locate element: {"method":"cssselector","selector":"span[id^='d2l_1_24']>a[title='Expand News']"}


The funny thing is when I use FireFox firebug to locate the element I have no difficulties with the following:

span[id^='d2l_1_24']>a[title='Expand News']
span[id^='d2l_1_24']>a[title='Collapse News']


It always returns a node.

After some investigation of previous questions I ruled out that the widget is on a separate iFrame. The dev tools indicate it is on the top window.

The HTML is as follows:

<div id="d2l_1_169_906" class="d2l-widget-header d2l-widget-header-clickable d2l_1_166_935 d2l_1_167_808 d2l_1_168_85 d2l_1_165_766" data-d2l-collapsed="d2l_1_165_766" onclick="D2L.O("__g1",25)()">
<div class="d2l-homepage-header-wrapper">
<div class="d2l-homepage-header-menu-wrapper">
<div class="d2l-homepage-header-collapse-wrapper">
<span id="d2l_1_24_470" class="d2l-expandcollapse d2l_1_117_742">
<a id="d2l_1_186_505" class="d2l-imagelink d2l_1_117_742 d2l_1_187_114 vui-outline" href="javascript:void(0);" onclick="return false;" title="Expand News" aria-label="Expand News" role="button"/>
<a id="d2l_1_188_574" class="d2l-imagelink d2l_1_117_742 d2l_1_189_251 vui-outline d2l-hidden" href="javascript:void(0);" onclick="return false;" title="Collapse News" aria-label="Collapse News" role="button"/>
</span>
</div>
<div class="d2l-clear"/>
</div>


My code is as follows:

//instance fields
static WebDriver driver;
private WebElement news_widget_expand;
private WebElement news_widget_collapse;

//constructor
public HomePage(){

WebDriver driver;

}

public void set_pageobject_news_widget_dropdown(WebDriver driver){

try {

driver.switchTo().defaultContent();
news_widget_collapse = driver.findElement(By.cssSelector("span[id^='d2l_1_24']>a[title='Expand News']"));
//news_widget_expand = driver.findElement(By.xpath(".//*[starts-with(@id, 'd2l_1_186')]"));
//news_widget_expand = driver.findElement(By.cssSelector("div[class='d2l-homepage']>div>div>div>div>span[id^='d2l_1_24']>a[title='Expand News']"));


news_widget_collapse = driver.findElement(By.cssSelector("span[id^='d2l_1_24']>a[title='Collapse News']"));
//news_widget_collapse = driver.findElement(By.xpath(".//*[starts-with(@id, 'd2l_1_188')]"));
//news_widget_expand = driver.findElement(By.cssSelector("div[class='d2l-homepage']>div>div>div>div>span[id^='d2l_1_24']>a[title='Collapse News']"));

} catch (Exception e) {
System.out.println("Couldnt set page objects");
e.printStackTrace();
}

}

public void collapse_news(WebDriver driver) throws InterruptedException{

try {
news_widget_collapse.click();
Thread.sleep(1000);
} catch (Exception e) {

e.printStackTrace();
System.out.println("Couldn't collapse the news widget...");
}
}

public void expand_news(WebDriver driver) throws InterruptedException{

try {
news_widget_expand.click();
Thread.sleep(1000);
} catch (Exception e) {

e.printStackTrace();
System.out.println("Couldn't expand the news widget...");
}


}

The code is called as follows:

Thread.sleep(2000);
//expand the widget
hp.set_pageobject_news_widget_dropdown(driver);
hp.expand_news(driver);


Is there anything obvious that I am missing here?

Answer Source

Not sure if this answer is much use to others but I managed to resolve it. I think this issue is due to some inexperience with working with css and html but I am able to get the above code working if I do the following:

news_widget_expand = driver.findElement(By.cssSelector("div.d2l-homepage-header-collapse-wrapper>span>a[title='Expand News']"));
news_widget_collapse = driver.findElement(By.cssSelector("div.d2l-homepage-header-collapse-wrapper>span>a[title='Collapse News']"));

I also did the following to confirm that the WebElements were in fact visible on the screen by creating a WebElement list getting all of the WebElements that had the specified cssSelector:

enter List<WebElement> buttons = driver.findElements(By.cssSelector("div.d2l-homepage-header-collapse-wrapper>span>a"));
        int noButtons = buttons.size();
        System.out.println("Total webelements = "+noButtons);
        if(noButtons>0){
            for(WebElement b : buttons){

                if( b.getAttribute("title").contains("Expand News"))
                    b.click();
                if( b.getAttribute("title").contains("Collapse News"))
                    b.click();


            }
        }else
            System.out.println(b.getAttribute("title"));code here

Once I confirmed that the page contained the elements I just modified the css to contain the attribute 'title' and set the instance field like this:

news_widget_expand = driver.findElement(By.cssSelector("div.d2l-homepage-header-collapse-wrapper>span>a[title='Expand News']"));

I wasted a lot of time on this trying different methods that get the Webdriver to click on the element, such as xpath and different cssselectors. I got there in the end and definitely looping through the WebElement gave me confident that the elements were in fact there.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download