SeleniumBase
SeleniumBase copied to clipboard
how method chaining works in seleniumbase?
Hi, I am using seleniumbase to automate our applications and it is very useful but i came across a scenario where i need to chain elements to click on element.
Here how to use method chaining or is there any solution for these kind of scenarios
# in GetModifyPage has this element: //span[contains(@id,'getTrainScheduleGrid')]/descendant::table[2]/tbody/tr/td[7]/span/span[not(text()='...')]
def add_etc_at_location(self):
etcs = self.find_elements(GetModifyPage.check_etc)
for i in range(len(etcs) - 1):
if (Utils.get_difference(etcs[i].text, etcs[i+1].text) >= 12):
etcs[i+1].find_element('preceding::tr[6]/td[7]/span/span').click() #its failing with InvalidArgument Error
Hi @anilreddy,
Your last line, etcs[i+1].find_element('preceding::tr[6]/td[7]/span/span').click() is failing because you switched to using a non-SeleniumBase / raw-selenium method.
self.find_element(selector) is a SeleniumBase call.
element.find_element(by, selector) is a raw Selenium call.
element.find_element(selector) will fail with InvalidArgumentException because you need to specify the by in this case.
In your case, you need to specify xpath as an argument first:
etcs[i+1].find_element('xpath', 'preceding::tr[6]/td[7]/span/span').click()
Also, SeleniumBase autodetects selector types (there's a detectable difference between css selectors and xpath selectors). Raw selenium methods do not have this auto-detection ability.
@mdmintz
It is now click on the element i needed after clicking on element am getting StaleElementReferenceException at if condition above if (Utils.get_difference(etcs[i].text, etcs[i+1].text) >= 12): Is there any alternative to this
support\base_testcase.py:313: in add_etc_at_location
if (Utils.get_difference(etcs[i].text, etcs[i+1].text) >= 12):
C:\software\Python310\lib\site-packages\selenium\webdriver\remote\webelement.py:84: in text
return self._execute(Command.GET_ELEMENT_TEXT)['value']
C:\software\Python310\lib\site-packages\selenium\webdriver\remote\webelement.py:396: in _execute
return self._parent.execute(command, params)
C:\software\Python310\lib\site-packages\selenium\webdriver\remote\webdriver.py:435: in execute
self.error_handler.check_response(response)
You'll get StaleElementReferenceException if one of the clicks you've chained together navigates the browser to a new page. You shouldn't have to use element.find_element() or element.click(), which are raw Selenium methods. You might be able to generate the selectors you need by using the SeleniumBase Recorder: https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/recorder_mode.md
If you need to click several similar elements, but you want the clicking to stop if the browser navigates to a new page, you can use self.click_visible_elements(selector), which will click all elements sequentially that match the selector.
I cannot use direct selector as I need to iterate through each element and get difference of time in hrs and if is >=12 then i need to click on that element.
That can be done without calling element.find_element(). Eg:
text1 = self.get_text(xpath1)
text2 = self.get_text(xpath2)
if int(text2) - int(text1) >= 12:
self.click(xpath2 + ' preceding::tr[6]/td[7]/span/span')
Add in the loop as needed, but you can avoid using element.find_element(by, selector).click(), which uses the raw selenium methods.
If you're still going to use element.find_element(by, selector).click(), you need to stop the clicking if there's a page load, because otherwise you'll get the StaleElementReferenceException.