ElementReferenceException when method chaining with Navigator

16 views
Skip to first unread message

Mark

unread,
Aug 7, 2017, 11:25:43 PM8/7/17
to Geb User Mailing List
This code is a pared-down version of some web scraping to isolate errors I'm experiencing in a minimal implementation.  I've narrowed it down to the difference between doing Navigator.$(selector)  and  $(full selector).   

import geb.Browser
System.setProperty("webdriver.chrome.driver", 'c:\\webdrivers\\chromedriver.exe')
Browser.drive {
  go
"https://www.uline.com/Product/GuidedNav?t=184360&dup=over" // direct to Shipping Boxes
 
assert title == 'ULINE - Shipping Boxes'
 
while (true) {
   
def table = $('table.GNItemTable')
   
assert table!=null && table.size()>0    
   
// def theader = table.$('thead tr th')  // usually fails after one page
   
def theader = $('table.GNItemTable thead tr th')  // never fails
   
def next = $('a.EnabledLink', text: 'Next>')
   
if (next == null || next.size() == 0) break;
   
next[0].click()
 
}
}

When I use method chaining; table.$('thead tr th') the code will fail with an ElementReferenceException usually on loading 2nd page.  When I use the full selector $('table.GNItemTable thead tr th') it runs consistently flawless.

Mark

unread,
Aug 7, 2017, 11:41:11 PM8/7/17
to Geb User Mailing List
It turns out a better work-around, since I only want to reference the first table, is to use
('table.GNItemTable',0 ).$('thead tr th')
which is a better fit for my needs, as I want to reference only the first table.

Still, any reason why the chaining form table.$('thead tr th') doesn't work?

Alexander Kriegisch

unread,
Aug 8, 2017, 3:38:12 AM8/8/17
to geb-...@googlegroups.com
You are having a timing issue. 'next[0].click()' is an asynchronous action changing the page content. You should use 'waitFor' in order to make sure that the page was actually updated as expected, e.g. like this:

go "https://www.uline.com/Product/GuidedNav?t=184360&dup=over" // direct to Shipping Boxes
assert title == 'ULINE - Shipping Boxes'
def currentPage = 1
while (true) {
waitFor { $("span.GNPaging a.DisabledLink")*.text().contains(currentPage.toString()) }
def table = $('table.GNItemTable')
assert table != null && table.size() > 0
def theader = table.$('thead tr th')
def next = $('a.EnabledLink', text: 'Next>')
if (next == null || next.size() == 0) break
next[0].click()
currentPage++
}

For me this works and fixes the problem.
--
Alexander Kriegisch
https://scrum-master.de

Mark

unread,
Aug 8, 2017, 3:10:11 PM8/8/17
to Geb User Mailing List
Thanks for the help!   You waitFor() approach which also confirms the expected page is loaded is great!

I had previously tried someone else's suggestion, which didn't help, which was to wrap the click in a waitFor

waitFor { next[0].click() }

Alexander Kriegisch

unread,
Aug 8, 2017, 3:23:24 PM8/8/17
to geb-...@googlegroups.com
Yes, it does not make sense to wait for an asynchronous action. ;-)
-- 
Alexander Kriegisch

--
You received this message because you are subscribed to the Google Groups "Geb User Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geb-user+u...@googlegroups.com.
To post to this group, send email to geb-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/geb-user/972bedce-c388-40db-ab4f-b5708c33f6a6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages