1

I've got an array of certain <a> elements like this:

array = browser.as(:class => 'foo')

I try to go to the links like this:

$i = 0
while $i < num do
    browser.goto array[$i].href
    .
    .
    .
    $i += 1
end

Which works the for the first loop, but not for the second. Why is this happening? If I do

puts array[1].href
puts array[2].href
puts array[-1].href

before

browser.goto array[$i].href

it shows all the links on the first loop in terminal window.

Forwarding
  • 245
  • 1
  • 12

2 Answers2

3

Someone who knows this better than I do will need to verify / clarify. My understanding is that elements are given references when the page is loaded. On loading a new page you are building all new references, even if it looks like the same link on each page.

You are storing a reference to that element and then asking it to go ahead and pull the href attribute from it. It works the first time, as the element still exists. Once the new page has loaded it no longer exists. The request to pull the attribute fails.

If all you care about are the hrefs there's a shorter, more Ruby way of doing it.

array = []

browser.as(:class => 'foo').each { |link|
  array << link.href
}

array.each { |link| 
  browser.goto link
}

By cramming the links into the array we don't have to worry about stale references.

3

Yes, unlike with individual elements that store the locator and will re-look them up on page reloads, an element collection stores only the Selenium Element which can't be re-looked up.

Another solution for when you need this pattern and more than just an href value is not to create a collection and to use individual elements with an index:

num.times do |i|
  link = browser.link(class: 'foo', index: i)
  browser.goto link.href
end
titusfortner
  • 4,099
  • 2
  • 15
  • 29