Take the 2-minute tour ×
Software Quality Assurance & Testing Stack Exchange is a question and answer site for software quality control experts, automation engineers, and software testers. It's 100% free, no registration required.

I'm looking for some advice on how to select a WebElement. When I click a button that creates a new 'page', the given value is dynamic, in that it is totally random and not sequential. I would expect it to follow something like: page 1 = 0, page 2 = 1, page 3 = 2, etc.

By default I begin with a page. Although when I trigger a button to create new pages the values appear as follows:

<select class="j-currentPage f-feature-A" name="currentPage">  <option value="c3">New Page</option>  <option value="c277">New Page 2</option>  <option value="c383">New Page 3</option>  <option selected="" value="c461">New Page 4</option>  </select>

So when I attempt to use the following:

 List<WebElement> option = chrome.findElements(By.tagName("option"));

    option.get(0).click();
    option.get(1).click();
    option.get(0).click();

It's obviously failing as the values are c277, c346 etc etc, and there is no way of knowing what the values will be in a new session as they will always be different.

The stacktrace is throwing a StaleElementReferenceException because its not in the DOM.

How can I select each page when the values are completely random?

I'm using Webdriver and JUnit4.

EDIT

Test method: to create some new pages.

@Test
public void createANewPage(){
    WebDriverWait wait = new WebDriverWait(chrome, 60);

    wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("select.j-currentPage.f-feature-A[name=\"currentPage\"]")));

    WebElement newPage = chrome.findElement(By.cssSelector("span.j-addViewBtn.ss-layers"));
    newPage.click();

    List<WebElement> option = chrome.findElements(By.tagName("option"));

    option.get(1).click();

    option.get(0).click();
}

Then a few tests later I want to call back the created page(s)

@Test
public void goToPage(){

    new WebDriverWait(chrome, 60).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("select.j-currentPage.f-feature-A[name=\"currentPage\"]")));
    List<WebElement> option = chrome.findElements(By.tagName("option"));

    option.get(0).click();
    option.get(1).click();
    option.get(0).click();
}

I receive a org.openqa.selenium.StaleElementReferenceException at the point of the third option.get(0).click();

However I feel as though I'm approaching this the wrong way as the values are dynamically created <option value="c3">New Page</option>
<option value="c207">New Page 2</option>
<option value="c288">New Page 3</option>
<option selected="" value="c366">New Page 4</option>

share|improve this question

3 Answers 3

If the element you are interacting with is being replaced in the DOM, which appears to be the case since you're getting a stale element exception, you'll need to find the element again rather than re-using the existing one. So for example, you would do this:

chrome.findElements(By.tagName("option")).get(0).click();
chrome.findElements(By.tagName("option")).get(1).click();
chrome.findElements(By.tagName("option")).get(0).click();

Another option would be to put it in a try/catch block and refresh only if an exception is caught. I found a good example of a generic method of waiting for all of your elements here: https://gist.github.com/djangofan/5112655

Whether the element is being generated dynamically or not is really kind of irrelevant, this happens any time an element is removed from the DOM and then re-added (including if you navigate to a new page and then back to the original page).

share|improve this answer

I would try to use xpath. And here I see two ways: 1) function contains(text(),'New Page') -- it searches by partial text, 2) function text()='New page \\d+' -- it searches every text 'New pages ' followed by numbers (using regex). Doing this allows you to avoid verifying dynamic values of elements.

share|improve this answer
WebElement selectButton = driver.findElement(By.name("currentPage"));
List<WebElement> list_selectButton = selectButton.findElements(By.tagName("option"));


List<String> list = new ArrayList<>(); {List stores the dynamic values of every option tag under select menu]


for(int i=0; i< list_selectButton-1; i++){

list.add(list_selectButton.get(i).getAttribute("value"));

}

//Now retrieve list contents and you can perform your tasks.

But, in order to click on every option element in your above scenario, I don't think you need to find the dynamic value, instead you can do something like this below ->

selectButton.click() // This will ensure that the option elements under it is now visible in the DOM and then you continue to click the option elements.

Thread.sleep(2000) // Delay because sometimes option elements will not be visible immediately, need to wait for sometime. You can add wait statements here instead.

list_selectButton.get(0).click
share|improve this answer
    
Thanks for your comments @user3164290 although your code does not seem to work. For instance, the diamonds after the ArrayList are not compatible with my language type. There is also another incompatible type with list_selectButton-1 as this seems to require a Boolean. Im interested to see how the ArrayList can capture the values. Any further explanation would be great. Thanks in advance. Also, the getAttribute("value")); method in the cannot be resolved. –  Django_Tester Jan 7 at 12:03
    
1. Can you tell me which language are you using? –  user3164290 Jan 9 at 7:26
    
Java with JUnit 4.11 as the execution framework. –  Django_Tester Jan 9 at 8:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.